[Nawiązanie do this Pytanie]Inicjacja shared_ptr <T> z unique_ptr <T[]>
Byłem trochę do czynienia z inteligentnymi wskaźniki do tablic c stylu niedawno. Ostatecznie nakręciłem zalecaną rzecz i zamiast tego użyłem inteligentnych wskaźników do wektorów, ale w tym okresie mam trochę rad: nie używaj obiektu shared_ptr<T>
do zarządzania tablicą początkowo wykonaną przy użyciu make_unique<T[]>
, ponieważ nie będzie ona wywoływać delete[]
ale raczej delete
.
To nie wydaje się logiczne, aby mnie i sprawdzone zarówno Coliru a średnia:
ten kod:
#include <iostream>
#include <memory>
int main()
{
std::cout << "start!\n";
auto customArrayAllocator = [](unsigned int num){
std::cout << "custom array allocator\n";
return new int[num];
};
std::cout << "allocator constructed\n";
auto customArrayDeleter = [](int *ptr){
std::cout << "custom array deleter\n";
delete[] ptr;
};
std::cout << "deleter constructed\n";
std::unique_ptr<int[], decltype(customArrayDeleter)>
myUnique(customArrayAllocator(4), customArrayDeleter);
std::cout << "unique_ptr constructed\n";
std::shared_ptr<int>
myShared = std::move(myUnique);
std::cout << "shared_ptr constructed\n";
}
produkuje ten wyjściowe:
start!
allocator constructed
deleter constructed
custom array allocator
unique_ptr constructed
shared_ptr constructed
custom array deleter
Co wydaje się wskazywać, że delikator unique_ptr<T[]>
jest przekazywany do shared_ptr<T>
, jak się spodziewałem.
Z C++ 14 standardowych § 20.8.2.2.1 pg. 571 of doc, 585 of pdf
szablon shared_ptr (unique_ptr & & r);
Uwaga: Ten konstruktor nie uczestniczy w przeciążeniu, chyba że unikalny_ptr :: wskaźnik jest zamienny na T *.
Wpływ: odpowiednik shared_ptr (r.release() r.get_deleter()), jeśli D nie jest typu odniesienia inaczej shared_ptr (r.release() Ref (r.get_deleter())).
Bezpieczeństwo wyjątków: Jeśli zostanie zgłoszony wyjątek, konstruktor nie wywoła żadnego efektu.
Jeśli czytam tego prawa, to znaczy, że shared_ptr
obiekt buduje się zarówno wskaźnik i Deleter z unique_ptr
. Ponadto, to moje zrozumienie (z odpowiedzi na oryginalne pytanie), że ::pointer
typu unique_ptr<T[]>
jest T*
, który powinien być zamienny na 's T*
. Deleter powinien być po prostu skopiowany bezpośrednio z obiektu unique_ptr
, prawda?
Czy moja próba pracy tylko dlatego, że nie jest właściwie równoznaczne z funkcji std::make_shared<T[]>
, czy składnia
std::shared_ptr<T> mySharedArray = std::make_unique<T[]>(16);
dobry, wyjątek bezpieczne (i czystsze) alternatywą dla
std::shared_ptr<T> mysharedArray(new T[16], [](T* ptr){delete[] ptr;});
i jej pochodne, gdy nie mogę użyć Boost's shared array i chcę uniknąć dołączenia nagłówka vector
lub array
h mój kod?
N.B. chociaż tablica ma zagwarantowane poprawne usunięcie, istnieje potencjalny problem z bezpieczeństwem podczas konwersji 'unique_ptr' -> 'shared_ptr ' -> 'shared_ptr ', zobacz http://stackoverflow.com/q/32483375/981959 –