2016-07-15 18 views
9

Jak rozumiem, to może zapewnić trochę optymalizacji alokacji pamięci (może przydzielić licznik referencyjny w obrębie tego samego bloku pamięci, co instancja klasy T).Czy enable_shared_from_this i make_shared zapewniają tę samą optymalizację

Czy opcja enable_shared_from_this zapewnia taką samą optymalizację? Więc:

class T : std::enable_shared_from_this<T> {}; 
... 
auto t = std::shared_ptr<T>(new T); 

jest taka sama jak:

class T {}; 
... 
auto t = std::make_shared<T>(); 

Jeśli nie uwzględniające sizeof (T).

+5

Oba są całkowicie ortogonalne. 'enable_shared_from_this' jest istotne, gdy * masz już * wspólny wskaźnik. –

+0

@KerrekSB Przypuszczam, że enable_shared_from_this dodaje niektóre dane do klasy, które mogą być używane przez implementację współdzielonego wskaźnika. Jeśli chodzi o mnie, najprostszy sposób - polega na umieszczeniu liczby odwołań w ramach opcji enable_shared_from_this, co może pomóc w zmniejszeniu alokacji pamięci w pierwszym przypadku. –

+0

Kusi mnie, aby powiedzieć "tak", ponieważ w przeciwnym razie nie ma sposobu na odzyskanie bloku refcount z wnętrza obiektu. Ale to tylko przeczucie. – Quentin

Odpowiedz

8

Czy enable_shared_from_this zapewnia taką samą optymalizację? A więc:

Nie. Jak widać na podstawie sformułowania w standardzie, enable_shared_from_this<T> ma element danych weak_ptr<T>. To dodaje weak_ptr<T> do klasy, która ma wskaźnik do bloku kontrolnego, który zawiera liczniki odwołań. Nie zawiera bezpośrednio referencji. Blok kontrolny zawierający liczniki referencyjne nadal istnieje na zewnątrz obiektu.

Blok sterujący zawierający liczniki referencyjne musi przeżyć obiekt, aby inne obiekty weak_ptr, które odnosiły się do obiektu, nadal mogły uzyskać dostęp do bloku sterującego, aby sprawdzić, czy wygasł.

Jeśli blok kontrolny znajdował się wewnątrz obiektu, zostanie zniszczony, gdy obiekt zostanie zniszczony, a nie będzie możliwe bezpieczne ustalenie, czy obiekt wygasł. Teoretycznie pamięć bloku kontrolnego mogłaby zostać przydzielona i nadal używana, a licznik odwołań został zaktualizowany, nawet jeśli obiekt, którego był częścią, został zniszczony, ale wydaje się to dość brzydkie (i oznaczałoby, że obiekt nie zostałby zniszczony przy pomocy delete , wymagałoby jawnego wywołania destruktora i wyraźnego wywołania w celu zwolnienia pamięci).

Nie można również użyć wbudowanego bloku sterującego, jeśli własność shared_ptr została utworzona za pomocą niestandardowego narzędzia lub niestandardowego programu przydzielania, ponieważ rozmiar tych obiektów nie byłby wcześniej znany. W takich przypadkach nadal trzeba by przydzielić zewnętrzny blok kontrolny oprócz, który jest osadzony w klasie bazowej, marnując jeszcze więcej miejsca.

+0

Dzięki za doskonałe wyjaśnienie! –

+0

To dość ciekawe pytanie, ale im więcej myślę o tym, jak to działa, tym więcej komplikacji znajdę. –

+0

Przypuszczam, że w przypadku make_shared pamięć instancji również nie może zostać zwolniony aż do ostatniego słabego punktu punktów do bloku sterującego. Ale w przeciwieństwie do enable_shared_from_this można to wyraźnie zaimplementować z punktu języka C++ (nie używaj zniszczonego obiektu). –

Powiązane problemy