Świat, w którym żyje Bjarne, jest bardzo ... akademicki, z braku lepszego określenia. Jeśli kod można zaprojektować i ustrukturyzować w taki sposób, że obiekty mają bardzo przemyślane hierarchie relacyjne, tak że relacje własności są sztywne i nieugięte, kod przepływa w jednym kierunku (od wysokiego poziomu do niskiego poziomu), a obiekty rozmawiają tylko z tymi niższymi hierarchii, wtedy nie będzie wiele potrzeby shared_ptr. Jest to coś, czego używasz w tych rzadkich przypadkach, gdy ktoś musi złamać zasady. Ale w przeciwnym razie możesz po prostu wsadzić wszystko w vectors lub inne struktury danych, które używają semantyki wartości, i unique_ptrs dla rzeczy, które musisz przydzielić pojedynczo.
Chociaż jest to świetny świat do życia, to nie jest to, co możesz robić przez cały czas. Jeśli nie możesz zorganizować swojego kodu w ten sposób, ponieważ konstrukcja systemu, który próbujesz stworzyć, oznacza, że jest to niemożliwe (lub po prostu głęboko nieprzyjemne), będziesz potrzebować wspólnej własności obiektów coraz bardziej .
W takim systemie trzymanie nagich wskazówek nie jest ... dokładnie niebezpieczne, ale rodzi pytania. Wspaniałą rzeczą shared_ptrjest to, że zapewnia rozsądne składniowe gwarancje dotyczące żywotności obiektu. Czy można to zepsuć? Oczywiście. Ale ludzie mogą także const_castrzeczy; podstawowa opieka i karmienie shared_ptrpowinny zapewniać rozsądną jakość życia przydzielonym obiektom, których własność musi być dzielona.
Są też weak_ptrs, których nie można użyć przy braku a shared_ptr. Jeśli twój system ma sztywną strukturę, możesz zapisać nagi wskaźnik do jakiegoś obiektu, wiedząc, że struktura aplikacji zapewnia, że wskazany obiekt przeżyje cię. Możesz wywołać funkcję, która zwraca wskaźnik do jakiejś wartości wewnętrznej lub zewnętrznej (na przykład znajdź obiekt o nazwie X). We właściwie skonstruowanym kodzie funkcja ta byłaby dostępna tylko wtedy, gdy gwarantowano by, że czas życia obiektu przekroczy twój; w ten sposób przechowywanie nagiego wskaźnika w obiekcie jest w porządku.
Ponieważ tej sztywności nie zawsze można osiągnąć w rzeczywistych systemach, potrzebujesz sposobu, aby zapewnić rozsądną trwałość. Czasami nie potrzebujesz pełnej własności; Czasami musisz po prostu wiedzieć, kiedy wskaźnik jest zły lub dobry. Tam właśnie weak_ptrprzychodzi. Były przypadki, w których mogłem użyć unique_ptrlub boost::scoped_ptr, ale musiałem użyć, shared_ptrponieważ szczególnie potrzebowałem dać komuś „niestabilny” wskaźnik. Wskaźnik, którego życie było nieokreślone, mogli zapytać, kiedy wskaźnik ten zostanie zniszczony.
Bezpieczny sposób na przetrwanie, gdy stan świata jest nieokreślony.
Czy można to zrobić za pomocą jakiegoś wywołania funkcji, aby uzyskać wskaźnik, zamiast przez weak_ptr? Tak, ale to może być łatwiejsze do złamania. Funkcja, która zwraca nagi wskaźnik, nie ma możliwości syntaktycznego sugerowania, że użytkownik nie robi czegoś takiego jak przechowywanie tego wskaźnika w dłuższej perspektywie. Zwrócenie a shared_ptrtakże sprawia, że zbyt łatwo jest go po prostu przechowywać i potencjalnie przedłużyć żywotność obiektu. Zwrócenie weak_ptrjednak zdecydowanie sugeruje, że przechowywanie tego, shared_ptrco otrzymujesz, lockjest ... wątpliwym pomysłem. Nie powstrzyma cię to przed zrobieniem tego, ale nic w C ++ nie powstrzyma cię przed złamaniem kodu. weak_ptrzapewnia minimalny opór przed robieniem rzeczy naturalnych.
To nie znaczy, że shared_ptrnie można tego nadużywać ; z pewnością może. Szczególnie wcześniej- unique_ptrbyło wiele przypadków, w których właśnie użyłem, boost::shared_ptrponieważ musiałem przekazać wskaźnik RAII lub umieścić go na liście. Bez przemieszczania się i semantyki unique_ptr, boost::shared_ptrbył jedynym realnym rozwiązaniem.
I możesz go używać w miejscach, w których jest to zupełnie niepotrzebne. Jak wspomniano powyżej, odpowiednia struktura kodu może wyeliminować potrzebę niektórych zastosowań shared_ptr. Ale jeśli twój system nie może być skonstruowany jako taki i nadal robi to, co musi, shared_ptrbędzie bardzo przydatny.