2012-04-23 15 views
5

Podczas inicjalizacji shared_ptr członek zmiennej:Inicjowanie zmienną składową shared_ptr, nowe kontra make_shared?

// .h 
class Customer 
{ 
public: 
    Customer(); 

private: 
    std::shared_ptr<OtherClass> something_; 
} 

// .cpp 
Customer(): 
    something_(new OtherClass()) 
{ 
} 

vs.

Customer(): 
    something_(std::make_shared<OtherClass>()) 
{ 
} 

jest wersja make_shared dozwolone? Zawsze wydaje mi się, że pierwsza wersja jest preferowana?

+4

Herb Sutter właśnie napisał GOTW na ten temat. Zobacz [to] (http://herbsutter.com/gotw/_103/), a także sprawdź [jeden problem] (http://lanzkron.wordpress.com/2012/04/22/make_shared-almost-a-silver -bullet /), którego Herb nie podaje wprost. –

+0

@RSamuelKlatchko - Zaktualizowany link do pierwszego linku podanego w ansewer use https://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/ –

Odpowiedz

11

Jedyne chwile, kiedy make_shared jest nie dozwolone są:

  1. Jeśli otrzymujesz nagą wskaźnik przydzielonego przez kogoś innego i przechowywanie go w shared_ptr. Zdarza się to często w przypadku współpracy z C API.
  2. Jeśli konstruktor, do którego chcesz zadzwonić, nie jest publiczny (make_shared może wywoływać tylko publiczne konstruktory). Może się to zdarzyć w przypadku funkcji fabrycznych, w których chcesz zmusić użytkowników do utworzenia obiektu z fabryki.

    Istnieją jednak sposoby na obejście tego. Zamiast prywatnego konstruktora, należy mieć publicznego konstruktora. Ale spraw, aby konstruktor wziął pod uwagę typ, może być zbudowany tylko przez osoby z prywatnym dostępem do klasy. W ten sposób jedynymi osobami, które mogą wywołać make_shared z tym typem obiektu, są osoby z prywatnym dostępem do klasy.

Tak, możesz to zrobić.

+0

Jeśli chodzi o kwestię przyjaźni, czy jest jakiś wspomnieć w Standardzie o konkretnej funkcji do wykorzystania jako przyjaciele? Mógłbym dobrze wyobrazić sobie jakąś implementację delegującą tę pracę do funkcji pomocniczych ... –

+0

@MatthieuM .: Byłem trochę ciekaw, to samo, dlatego powiedziałem "może być w stanie". Zapytałem o comp.std.C++; zobaczymy, co mają do powiedzenia na ten temat. Jeśli nie, to myślę, że może to przynieść porządny raport o wadzie. –

3

W tym przypadku używanie make_shared jest nie tylko dozwolone, ale lepiej jest z niego korzystać. Jeśli użyjesz nowego, przydzieli on pamięć dla twojego Klienta gdzieś, a potem pamięć twojego shared_ptr gdzie indziej, przechowując zarówno silne, jak i słabe referencje (dla słabych wskaźników i współdzielonych wskaźników). Jeśli używasz make_shared, masz tylko jedno miejsce w pamięci ze wszystkim i dlatego tylko jeden nowy.

Nie jestem pewien, czy naprawdę było jasne, to był cel GotW #103, przeczytaj, jest tam dobrze wyjaśniony.

Powiązane problemy