Czy std::make_unique
ma jakieś korzyści związane z wydajnością std::make_shared
?
W porównaniu z tworzeniem ręcznym std::unique_ptr
:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
c++
c++11
c++14
smart-pointers
unique-ptr
NFRCR
źródło
źródło
make_shared
ma jakąkolwiek skuteczność w porównaniu z samym pisaniem kodu długiej ręki?make_shared
może przydzielić zarówno miejsce na obiekt, jak i miejsce na blok sterujący razem w jednej alokacji. Kosztem tego jest to, że obiekt nie może zostać zwolniony oddzielnie od bloku sterującego, więc jeśli używaszweak_ptr
dużo, możesz skończyć z użyciem większej ilości pamięci.Odpowiedzi:
Motywacja
make_unique
jest przede wszystkim dwojaka:make_unique
jest bezpieczny do tworzenia tymczasowych, natomiast przy jawnym użyciunew
należy pamiętać o zasadzie nieużywania nienazwanych tymczasowych.Dodanie
make_unique
wreszcie oznacza, że możemy powiedzieć ludziom, aby „nigdy” nie używali,new
a nie poprzednią regułę, aby „nigdy” nie używali,new
z wyjątkiem sytuacji, gdy zrobiszunique_ptr
".Jest też trzeci powód:
make_unique
nie wymaga nadmiarowego użycia typu.unique_ptr<T>(new T())
->make_unique<T>()
Żaden z powodów nie wiąże się z poprawą wydajności czasu wykonywania w sposób, w jaki używa się
make_shared
tego (ze względu na unikanie drugiej alokacji, kosztem potencjalnie wyższego szczytowego wykorzystania pamięci).* Oczekuje się, że C ++ 17 będzie zawierał zmianę reguły, która oznacza, że nie jest to już niebezpieczne. Zobacz dokumenty komisji C ++ P0400R0 i P0145R3 .
źródło
std::unique_ptr
istd::shared_ptr
dlaczego możemy powiedzieć ludziom, aby „nigdy nie używalinew
”.make_shared
i takmake_unique
jest ostatni element, którego wcześniej brakowało.f
:f(unique_ptr<T>(new T), function_that_can_throw());
- by zacytować odpowiedź: Kompilator jest dozwolony do rozmowy (w kolejności):new T
,function_that_can_throw()
,unique_ptr<T>(...)
. Oczywiście, jeślifunction_that_can_throw
faktycznie rzuca, to wyciekasz.make_unique
zapobiega temu przypadkowi. Więc mam odpowiedź na moje pytanie.std::make_unique
istd::make_shared
są z dwóch powodów:std::unique_ptr
lubstd::shared_ptr
konstruktorów. (Zobacz sekcję Uwagi tutaj ).Tak naprawdę nie chodzi o wydajność czasu wykonywania. Jest trochę o bloku kontrolnym i
T
przydzielaniu wszystkiego naraz, ale myślę, że to bardziej bonus, a mniej motywacja do istnienia tych funkcji.źródło
std::make_shared
zapewni, że co najmniej jeden z nich zostanie zawinięty w inteligentny wskaźnik, zanim nastąpi alokacja innej pamięci, stąd nie ma wycieków.Powód, dla którego musiałbyś użyć
std::unique_ptr(new A())
lubstd::shared_ptr(new A())
bezpośrednio zamiaststd::make_*()
nie jest w stanie uzyskać dostępu do konstruktora klasyA
poza bieżącym zakresem.źródło
Rozważ wywołanie funkcji
Załóżmy, że new się
A()
powiedzie, ale newB()
rzuca wyjątek: łapiesz go, aby wznowić normalne wykonywanie programu. Niestety, standard C ++ nie wymaga, aby obiekt A został zniszczony, a jego pamięć zwolniona: pamięć po cichu przecieka i nie ma możliwości jej wyczyszczenia. Owijając A i B,std::make_uniques
masz pewność, że wyciek nie nastąpi:Chodzi o to, że
std::make_unique<A>
istd::make_unique<B>
są teraz obiektami tymczasowymi, a czyszczenie obiektów tymczasowych jest poprawnie określone w standardzie C ++: ich destruktory zostaną wyzwolone, a pamięć zwolniona. Więc jeśli możesz, zawsze wolisz przydzielać obiekty za pomocąstd::make_unique
istd::make_shared
.źródło