2011-01-02 9 views
18

uczę się o inteligentnych wskaźników (std::auto_ptr) i po prostu czytać here i here że inteligentne wskaźniki (std::auto_ptr) nie należy umieszczać w pojemnikach (tj std::vector), ponieważ nawet większość kompilatory nie będzie narzekać i mogłoby się wydawać poprawne. Nie ma reguły, która mówi, że inteligentne wskaźniki nie będą kopiowane wewnętrznie (na przykład przez klasę vector) i przenoszą własność, wtedy wskaźnik stanie się NULL. W końcu wszystko będzie spieprzone.Inteligentne wskaźniki w pojemniku takim jak std :: vector?

W rzeczywistości, jak często to się dzieje?

Czasami mam wektory wskaźników i jeśli w przyszłości zdecyduję, że chcę mieć wektor inteligentnych wskaźników, jakie byłyby moje opcje?

Jestem świadomy C++ 0x i Boost bibliotek, ale na razie wolałbym trzymać się podejścia STL.

+2

Istnieją również inteligentne wskaźniki w std :: tr1 (std :: tr1 :: shared_ptr) –

+1

Nie nazwałbym "auto_ptr" inteligentnym wskaźnikiem :) To naprawdę głupie, dlatego większość porad dotyczących inteligentnych wskaźników nie może (niestety) należy do niego zastosować (ze względu na jego skręconą semantykę kopiowania). –

Odpowiedz

16

Tak, ty naprawdę nie można używać std::auto_ptr ze standardowymi pojemnikami. std::auto_ptr kopie nie są równoważne, a ponieważ standardowe kontenery (i algorytmy) mogą kopiować ich elementy w dowolnym momencie, to wszystko się poprawia. Oznacza to, że operacja kopiowania pliku std::auto_ptr ma inną wartość niż zwykła kopia obiektu: oznacza to, że przenosi własność na własność .

wyboru są następujące opcje:

  1. Użyj Boost Smart Pointers library. Jest to prawdopodobnie najlepsza opcja.
  2. Użyj prymitywnych wskaźników. Jest to szybkie i bezpieczne, o ile prawidłowo zarządzasz wskaźnikami. Czasami może to być skomplikowane lub trudne. Na przykład będziesz musiał sam sobie poradzić z (unikaniem) podwójnego usuwania problemów.
  3. Użyj własnego inteligentnego wskaźnika zliczającego referencje. To byłoby głupie; użyj Wzmocnionego Inteligentnego Wskaźnika.
+3

Nie zapomnij o boost 'ptr_vector' i podobnie. – etarion

+8

Jeśli jesteś na kompilatorze, który go obsługuje, opcja 'unique_ptr' również jest opcją. – jalf

+2

Nie zgadzam się z ideą, że 'shared_ptr' jest najlepszą opcją. Widzę je jako opcję ostateczną, ponieważ współwłasność przynosi wiele problemów z powodu nieokreśloności życia: tak obiekt będzie żył tak długo, jak tego potrzebujesz, ale może również pozostać przy życiu o wiele dłużej, zwłaszcza jeśli nieumyślnie Stwórz cykl odniesień ... –

9

Problem, o którym mówisz dotyczy auto_ptr, ponieważ przenosi prawo własności do kopii. shared_ptr i unique_ptr działają dobrze z kontenerami.

3

Każdy typ używany ze standardowym szablonem kontenera musi odpowiadać wymaganiom tego kontenera. W szczególności typ musi spełniać wymagania dla typów CopyConstructible i Assignable.

Wiele inteligentnych wskaźników spełnia te wymagania i może być używany ze standardowymi pojemnikami, ale std::auto_ptr nie jest jednym z nich, ponieważ kopie std::auto_ptr nie są odpowiednikiem źródła, z którego zostały utworzone lub przypisane.

Mimo że niektóre implementacje standardowego kontenera mogą pracować z auto_ptr, w niektórych sytuacjach korzystanie z takich szczegółów implementacji jest niebezpieczne.

2

teoretycznie można użyć std::auto_ptr z kontenerów STL, jeśli całkowicie zrozumieć ich wewnętrzną implementację i wszystko, co można stracić auto_ptr własność nie rób, ale praktycznie jest to o wiele bardziej bezpieczny w użyciu pojemników z surowych ptrs.

"Jak często to się dzieje?" - samo w sobie jest bardzo niebezpiecznym pytaniem.Przede wszystkim STL - to nie jest jedna standardowa implementacja, jest ich wiele. Każdy może implementować kontenery na różne sposoby, więc twój wysoko dostrojony kod, aby ominąć wszystkie kopalnie "auto_ptr in containers", może przejść na inną implementację STL. Również obsługa kodu będzie bardzo skomplikowana, każda poprawna zmiana kodu może spowodować uszkodzenie programu. jak możesz to zapamiętać lub zmusić innych opiekunów do zapamiętania? umieszczanie ostrzeżeń w dowolnym miejscu, w którym takie zmiany mogą wystąpić? niemożliwy.

więc wniosek: to po prostu zły pomysł, który przynosi nic poza bólem głowy

+0

Teoretycznie iw wielu praktycznych przypadkach 'std :: vector >' nawet nie kompiluje. Bez względu na zrozumienie może ci w tym pomóc, kiedy standard po prostu zabrania tego. – MSalters

+1

std :: wektor > kompiluje dobrze w VC9, czy nie jest to zachowanie zgodne z normą? –

1

dla klas, które mają element danych auto ptr, zawsze mam metodę klonowania, która zwraca nowy auto ptr. Następnie zaimplementowałem metodę przypisania i skopiowałem konstruktora, który wywołuje metodę klonowania (i nigdy nie jest domyślnym operatorem przypisania auto ptr). W ten sposób możesz bezpiecznie używać klasy w pojemnikach STL.

Powiązane problemy