util.smartptr.shared.const / 9 w C ++ 11:
Efekty: Konstruuje obiekt shared_ptr, który jest właścicielem obiektu p i usuwacza d. Drugi i czwarty konstruktor używają kopii pamięci w celu alokacji pamięci do użytku wewnętrznego.
Drugi i czwarty konstruktor mają następujące prototypy:
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template<class D, class A> shared_ptr(nullptr_t p, D d, A a);
W najnowszej wersji pliku util.smartptr.shared.const / 10 jest równoważny z naszym celem:
Efekty: Konstruuje obiekt shared_ptr, który jest właścicielem obiektu p i usuwacza d. Gdy T nie jest typem tablicy, pierwszy i drugi konstruktor umożliwiają share_from_this z p. Drugi i czwarty konstruktor używają kopii pamięci w celu alokacji pamięci do użytku wewnętrznego. Jeśli zgłoszony zostanie wyjątek, wywoływane jest d (p).
Dlatego alokator jest używany, jeśli zachodzi potrzeba alokacji go w przydzielonej pamięci. Na podstawie obecnego standardu i na podstawie odpowiednich raportów o wadach przydział nie jest obowiązkowy, ale zakłada komitet.
Chociaż interfejs shared_ptr
pozwala implementacja tam, gdzie nigdy nie jest blok sterowania i wszystko shared_ptr
i weak_ptr
są umieszczane w połączonej listy, nie ma takiego wdrożenia w praktyce. Ponadto zmodyfikowano sformułowanie, zakładając na przykład, że use_count
jest ono wspólne.
Deleter jest wymagany tylko do ruchu konstrukcyjnego. Dlatego nie jest możliwe posiadanie kilku kopii w shared_ptr
.
Można sobie wyobrazić implementację, która umieszcza separator w specjalnie zaprojektowanym shared_ptr
i przenosi go, gdy jest shared_ptr
on usuwany. Chociaż implementacja wydaje się zgodna, jest to również dziwne, zwłaszcza, że do liczenia użycia może być potrzebny blok kontrolny (być może jest to możliwe, ale jeszcze dziwniejsze, aby zrobić to samo z liczbą użytych).
Odpowiednie DR, które znalazłem: 545 , 575 , 2434 (które potwierdzają, że wszystkie implementacje używają bloku sterującego i wydają się sugerować, że ograniczenia wielowątkowe w pewien sposób tego wymagają), 2802 (co wymaga, aby deleter poruszał się konstruowalnie, a tym samym uniemożliwiał implementację w przypadku, gdy usuwacz jest kopiowany pomiędzy kilkoma shared_ptr
.
a
) w celu zwolnienia tej pamięci. Co oznaczałoby pewne przechowywanie tej kopiia
. Brak informacji na ten temat w [util.smartptr.shared.dest].Od std :: shared_ptr mamy:
A od std :: przydzielate_shared otrzymujemy:
Wygląda więc na to, że std :: assignate_shared powinien przydzielić to
deleter
z twoimAlloc
.EDYCJA: I od
n4810
§20.11.3.6 Creation [util.smartptr.shared.create][Podkreśl wszystkie moje]
Tak więc standard mówi, że
std::allocate_shared
należy użyćAlloc
bloku kontrolnego.źródło
n4810
i zaktualizowano odpowiedź.make_shared
samych konstruktorach. Nadal mogę używać członka do małych programów usuwających.Uważam, że nie jest to określone.
Oto specyfikacja odpowiednich konstruktorów: [util.smartptr.shared.const] / 10
Moja interpretacja jest taka, że gdy implementacja potrzebuje pamięci do użytku wewnętrznego, robi to za pomocą
a
. Nie oznacza to, że implementacja musi wykorzystać tę pamięć do umieszczenia wszystkiego. Załóżmy na przykład, że jest taka dziwna implementacja:Czy ta implementacja „używa kopii w
a
celu przydzielenia pamięci do użytku wewnętrznego”? Tak. Nigdy nie przydziela pamięci, chyba że za pomocąa
. Jest wiele problemów z tą naiwną implementacją, ale powiedzmy, że przełącza się ona na używanie alokatorów we wszystkich, z wyjątkiem najprostszego przypadku, w którymshared_ptr
jest on konstruowany bezpośrednio ze wskaźnika i nigdy nie jest kopiowany, przenoszony ani w inny sposób przywoływany i nie ma innych komplikacji. Chodzi o to, że tylko dlatego, że nie wyobrażamy sobie prawidłowej implementacji, sama w sobie nie dowodzi, że nie może teoretycznie istnieć. Nie twierdzę, że taka implementacja może być faktycznie znaleziona w prawdziwym świecie, tylko że standard nie wydaje się aktywnie jej zabraniać.źródło
shared_ptr
dla małych typów przydziela pamięć na stosie. I tak nie spełnia standardowych wymagaństd::move(__d)
i cofnij się,allocate
gdy wymagana jest kopia.