Wskaźniki, Inteligentne Wskaźniki czy współdzielone wskaźniki? [duplikat]

To pytanie ma już odpowiedź tutaj:

Programuję za pomocą zwykłych wskaźników, ale słyszałem o bibliotekach takich jak Boost, które implementują Inteligentne Wskaźniki. Widziałem również, że w silniku renderowania Ogre3D jest głębokie wykorzystanie współdzielonych wskaźników.

Czym dokładnie jest różnica między tymi trzema, a czy powinienem trzymać się przy użyciu tylko jednego z nich?

 105
Author: Mateen Ulhaq, 2009-01-06

5 answers

Sydiusz dość dobrze opisał typy:

  • zwykłe wskaźniki są właśnie tym-wskazują na coś w pamięci. Do kogo należy? Tylko komentarze dadzą ci znać. Kto go uwalnia? Miejmy nadzieję, że właściciel w pewnym momencie.
  • Inteligentne Wskaźniki są ogólnym terminem obejmującym wiele typów; zakładam, że miałeś na myśli wskaźnik scoped, który używa wzoru RAII . Jest to obiekt przypisany do stosu, który zawija wskaźnik; gdy wychodzi poza zakres, wywołuje Usuń na wskaźniku, który zawija. "Posiada" zawarty wskaźnik, ponieważ jest odpowiedzialny za jego usunięcie w pewnym momencie. Pozwalają one uzyskać surowe odniesienie do wskaźnika, który zawijają w celu przekazania do innych metod, a także zwolnić Wskaźnik, pozwalając komuś innemu na jego posiadanie. Kopiowanie ich nie ma sensu.
  • Shared pointers jest obiektem przydzielonym do stosu, który zawija wskaźnik, dzięki czemu nie musisz wiedzieć, kto jest jego właścicielem. Gdy ostatni współdzielony wskaźnik dla obiektu jeśli pamięć zostanie zniszczona, zawinięty wskaźnik również zostanie usunięty.

A kiedy powinieneś ich użyć? Będziesz albo intensywnie korzystać ze wskaźników zakresowych lub wspólnych wskaźników. Ile wątków jest uruchomionych w Twojej aplikacji? Jeśli odpowiedź brzmi "potencjalnie dużo", udostępnione wskaźniki mogą okazać się wąskim gardłem wydajności, jeśli są używane wszędzie. Powodem jest to, że tworzenie/kopiowanie / niszczenie współdzielonego wskaźnika musi być operacją atomową, a to może utrudnić wydajność, jeśli działa wiele wątków. Jednak nie zawsze tak będzie - tylko testowanie powie ci na pewno.

Istnieje argument (który lubię) przeciwko współdzielonym wskaźnikom - używając ich, pozwalasz programistom ignorować, kto jest właścicielem wskaźnika. Może to prowadzić do trudnych sytuacji z okrągłymi odniesieniami (Java wykryje je, ale współdzielone wskaźniki nie mogą) lub ogólnego lenistwa programisty w dużej bazie kodu.

Istnieją dwa powody, dla których należy używać wskaźników z zakresami. Pierwszy jest dla prostych bezpieczeństwo wyjątków i operacje czyszczenia - jeśli chcesz zagwarantować, że obiekt zostanie oczyszczony bez względu na to, co się stanie w obliczu wyjątków, i nie chcesz przydzielać tego obiektu w stosie, umieść go w wskaźniku zasięgu. Jeśli operacja zakończy się sukcesem, możesz przenieść ją do współdzielonego wskaźnika, ale w międzyczasie zaoszczędź koszty ogólne za pomocą wskaźnika z lunetą.

Drugi przypadek dotyczy sytuacji, gdy chcesz mieć jasną własność obiektu. Niektóre zespoły wolą to, niektóre nie. Na przykład dane struktura może zwracać wskaźniki do obiektów wewnętrznych. Pod wskaźnikiem o zasięgu zwróci surowy wskaźnik lub odniesienie, które powinno być traktowane jako słabe odniesienie - jest to błąd, aby uzyskać dostęp do tego wskaźnika po zniszczeniu struktury danych, która jest jego właścicielem, i jest to błąd, aby go usunąć. Pod współdzielonym wskaźnikiem obiekt będący właścicielem nie może zniszczyć wewnętrznych danych, które zwrócił, jeśli ktoś nadal trzyma na nim uchwyt - może to pozostawić zasoby otwarte na znacznie dłużej niż to konieczne lub znacznie gorzej w zależności od kodu.

 138
Author: hazzen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-06 18:29:14

Termin " inteligentny wskaźnik "obejmuje współdzielone wskaźniki, automatyczne wskaźniki, wskaźniki blokujące i inne. miałeś na myśli auto pointer (bardziej dwuznacznie znany jako "posiadanie wskaźnika"), a nie inteligentny wskaźnik.

Głupie wskaźniki (T*) nigdy nie są najlepszym rozwiązaniem. Wymagają one wyraźnego zarządzania pamięcią, co jest gadatliwe, podatne na błędy, a czasami prawie niemożliwe. Ale co ważniejsze, nie sygnalizują Twoich zamiarów.

Auto pointers Usuń pointee przy niszczeniu. Do tablic, preferuje enkapsulacje takie jak vector i deque. W przypadku innych obiektów bardzo rzadko trzeba je przechowywać na stosie - wystarczy użyć lokacji i kompozycji obiektów. Wciąż pojawia się potrzeba automatycznych wskaźników z funkcjami, które zwracają wskaźniki sterty-takie jak fabryki i zwroty polimorficzne.

Wskaźnik współdzielony usuwa wskaźnik po zniszczeniu ostatniego współdzielonego wskaźnika. Jest to przydatne, gdy potrzebujesz bezproblemowego, otwartego systemu przechowywania, w którym oczekiwany okres użytkowania i własność mogą się różnić szeroko w zależności od sytuacji. Ze względu na konieczność utrzymywania licznika (atomowego) są one nieco wolniejsze niż wskaźniki automatyczne. Niektórzy mówią w połowie żartem, że wspólne wskaźniki są dla osób, które nie potrafią zaprojektować systemów-oceń sam.

Aby znaleźć odpowiednika współdzielonych wskaźników, sprawdź też słabe wskaźniki.

 31
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-06 18:21:32

Inteligentne Wskaźniki wyczyszczą się, gdy wyjdą poza zasięg (eliminując tym samym strach przed większością wycieków pamięci). Wskaźniki współdzielone to inteligentne wskaźniki, które utrzymują liczbę wystąpień wskaźnika i czyszczą pamięć tylko wtedy, gdy liczba ta osiągnie zero. Ogólnie rzecz biorąc, używaj tylko współdzielonych wskaźników (ale upewnij się, że używasz właściwego rodzaju-jest inny dla tablic). Mają wiele wspólnego z RAII .

 20
Author: Sydius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-06 18:11:00

Aby uniknąć wycieków pamięci, możesz użyć inteligentnych wskaźników, kiedy tylko możesz. Istnieją zasadniczo 2 różne typy inteligentnych wskaźników w C++

  • liczone odniesienia (np. boost::shared_ptr / std::tr1:shared_ptr)
  • nie liczone odniesienia (np. boost::scoped_ptr / std::auto_ptr)

Główna różnica polega na tym, że inteligentne wskaźniki z liczeniem referencji mogą być kopiowane (i używane w kontenerach std::), podczas gdy scoped_ptr nie może. Bez odniesienia liczone wskaźniki mają prawie żadnych napowietrznych lub żadnych kosztów. Liczenie referencji zawsze wprowadza jakiś rodzaj napowietrzności.

(proponuję unikać auto_ptr, ma kilka poważnych wad, jeśli jest używany nieprawidłowo)

 8
Author: d0k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-06 18:23:05

Aby dodać mały bit do odpowiedzi Sydiusa, Inteligentne Wskaźniki często zapewniają bardziej stabilne rozwiązanie poprzez wyłapywanie wielu łatwych do popełnienia błędów. Surowe wskaźniki będą miały pewne zalety perfromancji i mogą być bardziej elastyczne w pewnych okolicznościach. Możesz również być zmuszony do używania wskaźników surowych podczas łączenia się z niektórymi bibliotekami innych firm.

 5
Author: Shane MacLaughlin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-06 18:06:16