Z C ++ 17 , shared_ptr
mogą być używane do zarządzania dynamicznie przydzielonego tablicy. shared_ptr
Szablon argumentem w tym przypadku musi być T[N]
albo T[]
. Więc możesz pisać
shared_ptr<int[]> sp(new int[10]);
Od n4659, [util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
Wymagania: Y
muszą być kompletne. Wyrażenie delete[] p
, kiedy T
jest typem tablicowym lub delete p
, gdy T
nie jest typem tablicowym, powinno mieć dobrze zdefiniowane zachowanie i nie powinno generować wyjątków.
...
Uwagi: Gdy T
jest typem tablicowym, ten konstruktor nie będzie uczestniczył w rozpoznawaniu przeciążenia, chyba że wyrażenie delete[] p
jest poprawnie sformułowane i albo T
jest U[N]
i Y(*)[N]
jest konwertowane na T*
, albo T
jest
U[]
i Y(*)[]
jest konwertowane na T*
. ...
Aby to obsługiwać, typ pręta element_type
jest teraz zdefiniowany jako
using element_type = remove_extent_t<T>;
Dostęp do elementów tablicy można uzyskać za pomocą operator[]
element_type& operator[](ptrdiff_t i) const;
Wymaga: get() != 0 && i >= 0
. Jeśli T
jest U[N]
, i < N
. ...
Uwagi: Gdy T
nie jest typem tablicowym, nie jest określone, czy ta funkcja składowa jest zadeklarowana. Jeśli jest zadeklarowana, nie jest określone, jaki jest jej typ zwrotu, z wyjątkiem tego, że deklaracja (choć niekoniecznie definicja) funkcji powinna być poprawnie sformułowana.
Przed C ++ 17 , shared_ptr
mogłoby nie być używane do zarządzania dynamicznie przydzielone tablice. Domyślnie shared_ptr
wywoła delete
zarządzany obiekt, gdy nie będzie już do niego odwołań. Jednak podczas przydzielania zasobów new[]
musisz zadzwonić delete[]
, a nie delete
zwolnić zasób.
Aby poprawnie używać shared_ptr
z tablicą, musisz dostarczyć niestandardowy element usuwający.
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
Utwórz shared_ptr w następujący sposób:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
Teraz shared_ptr
będzie poprawnie dzwonić delete[]
podczas niszczenia zarządzanego obiektu.
Powyższy niestandardowy usuwacz może zostać zastąpiony przez
std::default_delete
częściowo kierunek typów tablicowe
std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
wyrażenie lambda
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
Ponadto, jeśli nie potrzebujesz współdzielenia zarządzanego obiektu, unique_ptr
lepiej nadaje się do tego zadania, ponieważ ma częściową specjalizację dla typów tablic.
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
Zmiany wprowadzone przez rozszerzenia C ++ dotyczące podstaw biblioteki
Inną alternatywą przed C ++ 17 do tych wymienionych powyżej była specyfikacja techniczna Library Fundamentals , która została rozszerzona, shared_ptr
aby umożliwić jej działanie od razu po wyjęciu z pudełka w przypadkach, gdy posiada tablicę obiektów. Aktualny projekt shared_ptr
zmian przewidzianych dla tego TS można znaleźć w N4082 . Te zmiany będą dostępne za pośrednictwem std::experimental
przestrzeni nazw i zawarte w <experimental/memory>
nagłówku. Oto kilka istotnych zmian dotyczących obsługi shared_ptr
tablic:
- element_type
Zmienia się definicja typu pręta
typedef T element_type;
typedef typename remove_extent<T>::type element_type;
- Członek operator[]
jest dodawany
element_type& operator[](ptrdiff_t i) const noexcept;
- W przeciwieństwie do unique_ptr
częściowej specjalizacji dla tablic, oba shared_ptr<T[]>
i shared_ptr<T[N]>
będą prawidłowe i oba spowodują delete[]
wywołanie z zarządzanej tablicy obiektów.
template<class Y> explicit shared_ptr(Y* p);
Wymagania : Y
muszą być kompletne. Wyrażenie delete[] p
, kiedy T
jest typem tablicowym lub delete p
, gdy T
nie jest typem tablicowym, powinno być poprawnie sformułowane, powinno mieć dobrze zdefiniowane zachowanie i nie powinno generować wyjątków. Kiedy T
jest U[N]
, Y(*)[N]
można zamienić na T*
; kiedy T
jest U[]
, Y(*)[]
można zamienić na T*
; w przeciwnym razie Y*
będzie można zamienić na T*
.
std::vector
. Musisz uważać, aby przekazać tablicę przy użyciu referencji, aby nie robić jej kopii. Składnia dostępu do danych jest czystsza niż shared_ptr, a zmiana jej rozmiaru jest bardzo łatwa. I dostajesz całą dobroć STL, jeśli kiedykolwiek chcesz.