Narzędzia użytkownika

Narzędzia witryny


smart_ptr

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Previous revision
Next revision
Previous revision
Last revision Both sides next revision
smart_ptr [2008/04/16 01:25]
wodny utworzono
smart_ptr [2008/04/16 01:48]
wodny
Linia 1: Linia 1:
 +{{libs:​smart_ptr:​smart_ptr_iso.cpp|}}
 <code cpp> <code cpp>
 +/*
 + * Autor: Marcin Szewczyk, 198370
 + *
 + * Temat: smart_ptr
 + *
 + * Inteligentne wskaźniki zawarte w module smart_ptr biblioteki boost.
 + * Sposób ich wykorzystania,​ różnice pomiędzy poszczególnymi typami wskaźników, ​
 + * nieco ciekawostek,​ które nie rzucają się od razu w oczy.
 + *
 + * Chociaż ten plik jest dość długi zawiera tylko garść informacji. Pełna ​
 + * dokumentacja,​ na której opierałem się pisząc ten program jest tu:
 + * http://​www.boost.org/​doc/​libs/​1_35_0/​libs/​smart_ptr/​smart_ptr.htm
 + *
 + * Omówione tutaj typy inteligentnych wskaźników to:
 + ​* ​ - scoped_ptr
 + ​* ​ - scoped_array
 + ​* ​ - shared_ptr
 + ​* ​ - weak_ptr
 + ​* ​ - intrusive_ptr
 + ​* ​ - oraz std::​auto_ptr nienależący do bibl. boost, ale warty porównania
 + *
 + ​* ​ nie został opisany typ shared_array,​ ponieważ nie wnosi nic nowego do 
 + ​* ​ omawianych tu zagadnień
 + */
  
 +#include <​cstdio>​
 +#include <​iostream>​
 +#include <​cstring>​
 +#include <​boost/​scoped_ptr.hpp>​
 +#include <​boost/​scoped_array.hpp>​
 +#include <​boost/​shared_ptr.hpp>​
 +#include <​boost/​weak_ptr.hpp>​
 +#include <​boost/​intrusive_ptr.hpp>​
 +#include <​boost/​enable_shared_from_this.hpp>​
 +#include <​vector>​
 +#include <​exception>​
 +
 +// ==========================================================
 +// Klasy potrzebne do prezentacji podstawowych cech inteligentnych wskaźników
 +
 +class Harry {
 + public:
 + Harry(const char* = NULL);
 + ~Harry();
 +
 + void hello();
 + private:
 + char *name;
 +};
 +
 +
 +class Betty : public Harry {
 + public:
 + Betty();
 + ~Betty();
 +};
 +
 +// ----------------------------------------------------------
 +
 +Harry::​Harry(const char *name_) {
 + name = name_ ? strdup(name_) : NULL;
 + printf("​-- Constructing Harry (%s)\n",​ name);
 +}
 +
 +Harry::​~Harry() {
 + printf("​-- Deconstructing Harry (%s)\n",​ name);
 +}
 +
 +void Harry::​hello() {
 + printf("​-- Harry \"​%s\"​ says hello\n",​ name);
 +}
 +
 +// ----------------------------------------------------------
 +
 +Betty::​Betty() {
 + printf("​---- Constructing Betty\n"​);​
 +}
 +
 +Betty::​~Betty() {
 + printf("​---- Deconstructing Betty\n"​);​
 +}
 +
 +// ==========================================================
 +// Klasa, która posłuży do prezentacji,​ jak radzą sobie inteligentne wskaźniki z 
 +// cyklami
 +//
 +// Wariant dla cyklu z użyciem shared_ptr
 +
 +class RingNode {
 + public:
 + RingNode(const char*, const boost::​shared_ptr<​RingNode>&​);​
 + ~RingNode();​
 + void connect(const boost::​shared_ptr<​RingNode>&​);​
 + const char* get_name();
 + const boost::​shared_ptr<​RingNode>&​ get_node();
 + private:
 + boost::​shared_ptr<​RingNode>​ node;
 + char* name;
 +};
 +
 +RingNode::​RingNode(const char* name_, const boost::​shared_ptr<​RingNode>&​ node_) : node(node_){
 + name = name_ ? strdup(name_) : NULL;
 + printf("​++ Constructing RingNode (%s)\n",​ name);
 +}
 +
 +RingNode::​~RingNode() {
 + printf("​++ Deconstructing RingNode (%s)\n",​ name);
 +}
 +
 +void RingNode::​connect(const boost::​shared_ptr<​RingNode>&​ node_) {
 + node = node_;
 +}
 +
 +const char* RingNode::​get_name() {
 + return name;
 +}
 +
 +const boost::​shared_ptr<​RingNode>&​ RingNode::​get_node() {
 + return node;
 +}
 +
 +// ----------------------------------------------------------
 +// Wariant cyklu z weak_ptr
 +
 +class WeakRingNode {
 + public:
 + WeakRingNode(const char*, const boost::​shared_ptr<​WeakRingNode>&​);​
 + ~WeakRingNode();​
 + void connect(const boost::​shared_ptr<​WeakRingNode>&​);​
 + const char* get_name();
 + const boost::​shared_ptr<​WeakRingNode>​ get_node();
 + private:
 + boost::​weak_ptr<​WeakRingNode>​ node;
 + char* name;
 +};
 +
 +WeakRingNode::​WeakRingNode(const char* name_, const boost::​shared_ptr<​WeakRingNode>&​ node_) : node(node_) {
 + name = name_ ? strdup(name_) : NULL;
 + printf("​++ Constructing RingNode (%s)\n",​ name);
 +}
 +
 +WeakRingNode::​~WeakRingNode() {
 + printf("​++ Deconstructing RingNode (%s)\n",​ name);
 +}
 +
 +void WeakRingNode::​connect(const boost::​shared_ptr<​WeakRingNode>&​ node_) {
 + node = node_;
 +}
 +
 +const char* WeakRingNode::​get_name() {
 + return name;
 +}
 +
 +const boost::​shared_ptr<​WeakRingNode>​ WeakRingNode::​get_node() {
 + return node.lock();​
 +}
 +
 +// ==========================================================
 +// Klasa potrzebna do prezentacji intrusive_ptr
 +//  czyli sama zwiększa/​zmniejsza ilość referencji do danego obiektu na zlecenie ​
 +//  intrusive_ptr oraz sama odpowiada za zniszczenie obiektu, gdy ilość odwołań ​
 +//  spadnie do zera
 +
 +class Intruded {
 + public:
 + Intruded();​
 + ~Intruded();​
 + private:
 + int counter;
 +
 + friend void intrusive_ptr_add_ref(Intruded *const);
 + friend void intrusive_ptr_release(Intruded *const);
 +};
 +
 +void intrusive_ptr_add_ref(Intruded *const);
 +void intrusive_ptr_release(Intruded *const);
 +
 +// ----------------------------------------------------------
 +
 +Intruded::​Intruded() : counter(0) {
 + printf("​%% Creating Intruded\n"​);​
 +}
 +
 +Intruded::​~Intruded() {
 + printf("​%% Destroying Intruded\n"​);​
 +}
 +
 +// Jak widać, licznik jest składową klasy, natomiast funkcje odpowiedzialne za 
 +// zliczanie - nie.
 +// Na podstawie typu parametru, intrusive pointer wybiera odpowiedni zestaw ​
 +// funkcji do inkrementacji i dekrementacji ilości odwołań
 +
 +void intrusive_ptr_add_ref(Intruded *const p) {
 + printf("​%% Added. Now: %d\n", ++(p->​counter));​
 +}
 +
 +void intrusive_ptr_release(Intruded *const p) {
 + printf("​%% Removed. Now: %d\n", --(p->​counter));​
 + if(!p->​counter) {
 + printf("​%% Deleting Intruded because of count == 0...\n"​);​
 + delete p;
 + }
 +}
 +
 +// ==========================================================
 +// Jak uzyskać poprawny (pod względem zliczania odwołań) shared_ptr do obiektu ​
 +// nie mając wiedzy na temat tego, czy już jakiś inny shared_ptr się do niego 
 +// odwołuje
 +
 +// Konieczne jest dziedziczenie klasy po enable_shared_from_this<>​
 +
 +class WithSharing : public boost::​enable_shared_from_this<​WithSharing>​ {
 +public:
 + boost::​shared_ptr<​WithSharing>​ get_shared() {
 + return shared_from_this();​
 + }
 +};
 +
 +// ==========================================================
 +// ==========================================================
 +// ==========================================================
 +
 +using namespace std;
 +
 +// By uniknąć bardzo długich definicji poniżej
 +typedef vector< boost::​shared_ptr<​Harry>​ > SharedHarryVector;​
 +
 +// ==========================================================
 +// Funkcja wyświetla nagłówek tekstowy podkreślony linijką
 +
 +void header(const char* label) {
 + char* bar = strdup(label);​
 + memset(bar,​ '​=',​ strlen(bar));​
 + cout << endl << label << endl << bar << endl;
 +}
 +
 +// ==========================================================
 +// ==========================================================
 +
 +// Funkcja jest wywoływana,​ ale szkodliwy fragment jest wykomentowany
 +void play_dirty_harry() {
 + header("​Dirty Harry - czego ze wskaznikami robic nie wolno"​);​
 +
 + Harry* tmp_harry;
 + boost::​scoped_ptr<​Harry>​ harry(tmp_harry = new Harry("​Simple Class Harry"​));​
 +
 + //​boost::​scoped_ptr<​Harry>​ harry2(tmp_harry);​
 + // Nielegalne - dwa scoped_ptr, każdy z liczbą odwołań = 1
 + // Podczas destrukcji dwóch scoped_ptr dochodzi dwa razy do próby destrukcji ​
 + // jednego obiektu klasy Harry. Lepiej przedstawi to shared_ptr, który pojawi ​
 + // się poniżej
 +
 + //​boost::​scoped_ptr<​Harry>​ harry_b(harry);​
 + // Kopiowanie scoped_ptr jest zakazane (konst. kopiujący w sekcji private)
 + //​boost::​scoped_ptr<​Harry>​ harry_c;
 + //harry_c = harry;
 + // Analogiczna uwaga dotyczy operatora przypisania
 +
 +}
 +
 +void play_nice_harry() {
 + header("​play_nice_harry - scoped_ptr jak zmienna automatyczna"​);​
 + // Jakieś tam zadania
 + // ...
 +
 + // Tutaj proste zastosowanie - scoped_ptr zachowuje się jak zmienna ​
 + // automatyczna. Po wyjściu poza zasięg, scoped_ptr niszczy siebie, a 
 + // wcześniej związany z nim obiekt.
 + //
 + // Stąd nazwa - scoped - czyli dot. zasięgu.
 + // Nawiązuje to do pomysłu "​resource acquisition is initialization"​. Zasoby ​
 + // są zajmowane w momencie inicjalizacji i, co ważniejsze,​ zwalniane podczas ​
 + // "​odinicjowania",​ czyli destrukcji po wyjściu poza zasięg.
 +
 + boost::​scoped_ptr<​Harry>​ harry3(new Harry("​Harry3"​));​
 + harry3->​hello();​
 +
 + Harry harry4("​Harry4"​);​
 + harry4.hello();​
 +
 +}
 +
 +void play_nice_harry3() {
 + // Jednak nie zawsze wystarcza nam zmienna automatyczna. Ciekawsze jest 
 + // dynamiczne powoływanie obiektów do życia operatorem "​new"​.
 +
 + header("​play_nice_harry3 - operator \"​new\"​ bez potrzeby wywolania delete"​);​
 + boost::​scoped_ptr<​Harry>​ harry7;
 +
 + //
 + // Coś tam do roboty...
 + bool needHarry = true;
 + // Coś tam do roboty...
 + //
 +
 + if(needHarry)
 +
 + harry7.reset(new Harry("​Harry7"​));​
 +
 + //
 + // Coś tam do roboty...
 + //
 +
 + if(harry7) {
 + printf("​-- Stwierdzlismy,​ ze harry7 sie przyda - wykonajmy na nim operacje\n"​);​
 + // Operacje na Harrym...
 + }
 +
 + // Normalnie w tym miejscu przydałoby się wywołanie delete na zwykłym ​
 + // wskaźniku. Ponieważ jednak nasz inteligenty wskaźnik jest zmienną ​
 + // automatyczną,​ sam usunie siebie i skojarzony obiekt
 +}
 +
 +void comfort_test() throw(exception) {
 + header("​Comfort test - shared_ptr jak zm. auto.; auto. usuwanie, gdy rzucany jest wyjatek"​);​
 + boost::​shared_ptr<​Harry>​ h1;
 + boost::​shared_ptr<​Harry>​ h2;
 +
 + // Coś tam...
 +
 + // Potrzebujemy Harry'​ego
 + h1.reset(new Harry("​Potter"​));​
 + h2.reset(new Harry("​Callahan"​));​
 + cout << "​Callahan count: " << h2.use_count() << endl;
 + h1 = h2;
 + cout << "​Callahan zjadl Pottera, count: " << h2.use_count() << endl;
 + cout << "h1: ";
 + h1->​hello();​
 + cout << "h2: ";
 + h2->​hello();​
 +
 + // Go ahead, make my day.
 + //   ​Rzucamy wyjątek
 + cout << "​Throwing an exception .44" << endl;
 + throw exception();​
 +}
 +
 +// Prezentacja,​ jak zachowują się intrusive_ptr
 +void test_intrusive_ptr() {
 + header("​test_intrusive_ptr"​);​
 + boost::​intrusive_ptr<​Intruded>​ i1(new Intruded);
 +}
 +
 +// Ciekawostka związana z shared_ptr
 +// Różnica, między tym, co deklarujemy jako klasę dla szablony shared_ptr, a 
 +// klasą parametru przekazywanego w konstruktorze. Jakie nieoczywiste zdarzenie ​
 +// może wystąpić, gdy destruktory klas są niewirtualne.
 +
 +void non_virt_diffs() {
 + header("​Niewirtualny destruktor. Roznice miedzy zwyklym wskaznikiem a shared_ptr"​);​
 + // Destructor nie jest wirtualny, stąd Betty nie jest niszczona
 + {
 + cout << "​Zwykly Harry-wskaznik na Betty" << endl;
 + Harry *hb = new Betty;
 + delete hb;
 + }
 +
 + // Nieco inaczej sprawa się przestawia dla shared_ptr
 + {
 + cout << endl << "​Betty-wskaznik na Betty w Harry-szablonie"​ << endl;
 + boost::​shared_ptr<​Harry>​ b1(new Betty);
 + // shared_ptr pamięta rzeczywisty typ wskaźnika przekazywanego w 
 + // parametrze. W związku z tym używa destruktora dla tego typu (Betty) ​
 + // zamiast typu deklarowanego w szablonie (Harry)
 + //  > przykładowa implementacja mechanizmu:
 + //  > http://​wodny.org/​download/​smart_ptr/​template_memory.cpp
 + }
 +
 + {
 + cout << endl << "​Harry-wskaznik na Betty w Harry-szablonie"​ << endl;
 + Harry *b3 = new Betty;
 + boost::​shared_ptr<​Harry>​ b2(b3);
 + // Tutaj shared_ptr nie ma okazji poznać prawdziwego typu obiektu.  ​
 + // Traktuje go jak Harry'​ego. Dla poprawnego działania, tu destruktor już 
 + // musi być wirtualny.
 + }
 +
 +}
 +
 +void play_scoped_array() {
 + // Prosty przykład, że inteligentne wskaźniki z dopiskiem _array służą do 
 + // kojarzenia ich z tablicami. Nie można by tu użyć scoped_ptr. Jest to 
 + // związane z obostrzeniem,​ że delete stosujemy dla pojedynczego obiektu, ​
 + // delete[] dla tablic. Inteligenty wskaźnik nie posiadając informacji o 
 + // naturze przekazanego wskaźnika źle zarządzałby pamięcią.
 + header("​Zabawy ze scoped_array"​);​
 + boost::​scoped_array<​Harry>​ harry_a1(new Harry[3]);
 +}
 +
 +void general_use() {
 + header("​Ogolny sposob uzycia shared_ptr"​);​
 +
 + Harry *hp1 = NULL;
 + boost::​shared_ptr<​Harry>​ harry_sp1(hp1 = new Harry("​Shared Harry1"​));​
 + cout << "​harry_sp1.use_count:​ " << harry_sp1.use_count() << endl;
 + //​boost::​shared_ptr<​Harry>​ harry_sp2(hp1);​
 + // Taka konstrukcja spowoduje błąd. Dwa shared_ptr będą próbowały usunąć dwa 
 + // razy ten sam obiekt podczas własnej destrukcji.
 + //
 + // Istotne jest, by zauważyć, że shared_ptr nie ma jakiejś ukrytej tablicy ​
 + // asocjacyjnej (trzymającej się np. wzorca Singleton), która pozwalałaby mu 
 + // stwierdzać,​ którymi wskaźnikami już się opiekuje.
 + // Poinformowanie o tym, że kolejny shared_ptr chce również odnosić się do 
 + // danego zwykłego wskaźnika następuje przez wykonanie konstruktora ​
 + // kopiującego (opcjonalnie operatora przypisania). Od tej pory każdy z 
 + // shared_ptr ustawi ilość odwołań na 2 i przy destrukcji jednego z nich, 
 + // drugi inteligenty wskaźnik dowie się o tym zdarzeniu i zdekrementuje ​
 + // własny licznik odwołań
 + // (Mowa jest tu o logice działania, nie rzeczywistej implementacji ​
 + // inteligentnego wskaźnika).
 + cout << "Czas, by podzielic sie zasobem"​ << endl;
 + boost::​shared_ptr<​Harry>​ harry_sp2(harry_sp1);​
 + boost::​shared_ptr<​Harry>​ harry_sp3;
 + harry_sp3 = harry_sp2;
 + cout << "​harry_sp1.use_count:​ " << harry_sp1.use_count() << endl;
 + cout << "​harry_sp2.use_count:​ " << harry_sp2.use_count() << endl;
 + cout << "​harry_sp3.use_count:​ " << harry_sp3.use_count() << endl;
 +
 +}
 +
 +SharedHarryVector* get_harries() {
 + // Shared_ptr a kontenery
 + // (scoped_ptr nie może zostać użyty do takich zastosowań - nie da się 
 + // skopiować kontenerowi,​ poza tym jego przeznaczenie jest inne)
 + header("​Wektor (vector) z Harrych - uzycie shared_ptr w kontenerach STL");
 +
 + SharedHarryVector *vect = new SharedHarryVector();​
 + boost::​shared_ptr<​Harry>​ h;
 + for(int i = 0; i < 4; ++i) {
 + h.reset(new Harry("​Vector Harry"​));​
 + cout << "Ilosc Harry'​ego przed wlozeniem do wektora: " << h.use_count() << endl;
 + vect->​push_back(h);​
 + cout << "Po wlozeniu: " << h.use_count() << endl;
 + }
 + return vect;
 +}
 +
 +void stl_container() {
 + // W nawiązaniu do powyższej funkcji
 + boost::​shared_ptr<​ SharedHarryVector > harry_vector(get_harries());​
 + cout << "​Liczność jednego z wektorowych Harrych: " << harry_vector->​front().use_count() << endl << endl;
 +}
 +
 +void no_cycle() {
 + header("​Bez cyklu"​);​
 + // Bez cyklu
 + boost::​shared_ptr<​RingNode>​ R3(new RingNode("​RingNode3",​ boost::​shared_ptr<​RingNode>​((RingNode*)NULL)));​
 + boost::​shared_ptr<​RingNode>​ R4(new RingNode("​RingNode4",​ boost::​shared_ptr<​RingNode>​(R3)));​
 + cout << "R3 (" << R4->​get_name() << ") with count " << R3.use_count() << endl;
 + cout << "R4 (" << R4->​get_name() << ") with count " << R4.use_count() << " connected to " << R4->​get_node()->​get_name() << endl;
 + // Wszystkie węzły ulegną zniszczeniu jak powinny
 +}
 +
 +void shared_cycle() {
 + header("​Cykl na shared_ptr"​);​
 + // Większy cykl, choć uzyskany tylko pośrednio, powoduje, że węzły nie 
 + // zostaną usunięte, ponieważ ilość odwołań w shared_ptr nie spadnie do zera
 + boost::​shared_ptr<​RingNode>​ R7(new RingNode("​RingNode7",​ boost::​shared_ptr<​RingNode>​((RingNode*)NULL)));​
 + boost::​shared_ptr<​RingNode>​ R8(new RingNode("​RingNode8",​ boost::​shared_ptr<​RingNode>​(R7)));​
 + boost::​shared_ptr<​RingNode>​ R9(new RingNode("​RingNode9",​ boost::​shared_ptr<​RingNode>​(R8)));​
 + R7->​connect(R9);​
 + cout << "R7 (" << R7->​get_name() << ") with count " << R7.use_count() << " connected to " << R7->​get_node()->​get_name() << endl;
 + cout << "R8 (" << R8->​get_name() << ") with count " << R8.use_count() << " connected to " << R8->​get_node()->​get_name() << endl;
 + cout << "R9 (" << R9->​get_name() << ") with count " << R9.use_count() << " connected to " << R9->​get_node()->​get_name() << endl;
 +
 + /*
 +    R7-->"​R7"<​--------------------.
 +           ​| ​                     |
 +           ​*--node-->"​R8"<​--R8 ​   |
 +                       ​| ​         |
 +                       ​*--node-->"​R9"<​--R9
 + */
 +}
 +
 +void weak_cycle() {
 + header("​Cykl na weak_ptr"​);​
 + // "​Słaby"​ cykl oparty o weak_ptr
 + boost::​shared_ptr<​WeakRingNode>​ R5(new WeakRingNode("​WeakRingNode5",​ boost::​shared_ptr<​WeakRingNode>​((WeakRingNode*)NULL)));​
 + boost::​shared_ptr<​WeakRingNode>​ R6(new WeakRingNode("​WeakRingNode6",​ boost::​shared_ptr<​WeakRingNode>​(R5)));​
 + R5->​connect(R6);​
 + boost::​weak_ptr<​WeakRingNode>​ Wtmp1(R5);
 + boost::​weak_ptr<​WeakRingNode>​ Wtmp2(R6);
 + // Jak można zauważyć, weak_ptr nie zwiększa licznika odwołań do obiektu, ​
 + // którego dotyczy, ani nie usuwa obiektu, gdy wielkość ta spadnie do zera.  ​
 + // Obiekt, do którego się odwołuje może zostać usunięty "bez jego wiedzy"​.  ​
 + // Dlatego właśnie współpracuje z shared_ptr.
 + cout << "R5 (" << R5->​get_name() << ") with count " << R5.use_count() << " connected to " << R5->​get_node()->​get_name() << endl;
 + cout << "R6 (" << R6->​get_name() << ") with count " << R6.use_count() << " connected to " << R6->​get_node()->​get_name() << endl;
 + // Poprzez funkcję weak_ptr.lock(),​ która użyta jest w get_node(), weak_ptr ​
 + // gwarantuje nam, że zostanie wykonana dodatkowa kopia, a shared_ptr zajmie ​
 + // się zwiększeniem licznika odwołań, by obiekt nie zniknął podczas ​
 + // wykonywania na nim operacji.
 + // Jeśli obiekt zdążył zniknąć już wcześniej, podczas tworzenia shared_ptr z 
 + // weak_ptr dostaniemy wyjątek bad_weak_ptr.
 +}
 +
 +void shared_and_weak() {
 + header("​Relacja miedzy shared_ptr i weak_ptr"​);​
 +
 + cout << "​Oryginalny shared_ptr:"​ << endl;
 + boost::​shared_ptr<​Harry>​ shared1(new Harry);
 + cout << "​shared1.count:​ " << shared1.use_count() << endl;
 +
 + cout << "​weak_ptr z shared_ptr:"​ << endl;
 + boost::​weak_ptr<​Harry>​ weak1(shared1);​
 + cout << "​shared1.count:​ " << shared1.use_count() << endl;
 + cout << "​weak1.count ​ : " << weak1.use_count() << endl;
 +
 + cout << "​shared_ptr z weak_ptr (z shared_ptr)"​ << endl;
 + boost::​shared_ptr<​Harry>​ shared2(weak1);​
 + cout << "​shared1.count:​ " << shared1.use_count() << endl;
 + cout << "​weak1.count ​ : " << weak1.use_count() << endl;
 + cout << "​shared2.count:​ " << shared2.use_count() << endl;
 +}
 +
 +void with_sharing_test(WithSharing&​ ws) {
 + header("​Test enable_shared_from_this<>"​);​
 +
 + boost::​shared_ptr<​WithSharing>​ ws_a(ws.get_shared());​
 + cout << "Drugi udzial, use_count: " << ws_a.use_count() << endl;
 + /*  .
 + * /|\
 + *  |
 + * -------------------------------------------------
 + * dwa niezależne fragmenty kodu, np. dwa wątki
 + * -------------------------------------------------
 + *  |
 + * \|/
 + *  '
 + */
 + boost::​shared_ptr<​WithSharing>​ ws_b(ws.get_shared());​
 + cout << "​Trzeci udzial, use_count: " << ws_b.use_count() << endl;
 +
 +}
 +
 +void auto_ptr_demo() {
 + header("​auto_ptr - przy boost maly sens stosowania"​);​
 + /*
 + * http://​gcc.gnu.org/​onlinedocs/​libstdc++/​libstdc++-html-USERS-4.0/​classstd_1_1auto__ptr.html
 + *
 + * "​auto_ptr does not meet the CopyConstructible and Assignable
 + * requirements for Standard Library container elements and thus
 + * instantiating a Standard Library container with an auto_ptr results in 
 + * undefined behavior."​
 + *
 + * Reasumując - auto_ptr ciekawy nie jest. Potrafi tylko oddawać powiązanie z 
 + * obiektem, natomiast nie potrafi się nim dzielić. Zastosowanie w 
 + * kontenerach nie jest możliwe.
 + */
 +
 + auto_ptr<​Harry>​ a1(new Harry);
 + cout << "NEW. " << a1.get() << endl;
 + auto_ptr<​Harry>​ a2(a1);
 + cout << "1st transfer, source: " << a1.get() << endl;
 + cout << "1st transfer, dest. : " << a2.get() << endl;
 + auto_ptr<​Harry>​ a3 = a2;
 + cout << "2nd transfer, source: " << a2.get() << endl;
 + cout << "2nd transfer, dest. : " << a3.get() << endl;
 +}
 +
 +// ==========================================================
 +// ==========================================================
 +// ==========================================================
 +
 +int main(int argc, char** argv) {
 + // ==========================================================
 + // Zestaw tego, czego robić nie wolno ze scoped_ptr
 + play_dirty_harry();​
 +
 + // shared_ptr
 + general_use();​
 +
 + // Mniej interesujące
 + play_nice_harry();​
 + // Bardziej interesujące
 + play_nice_harry3();​
 +
 + // scoped_array zamiast scoped_ptr - właściwe delete, konkretnie delete[]
 + play_scoped_array();​
 +
 + // Niewirtualny destruktor. Różnice między zwykłym wskaźnikiem a shared_ptr
 + non_virt_diffs();​
 +
 + // ==========================================================
 + // Kontener STL
 + stl_container();​
 +
 + // ==========================================================
 + // Shared vs Weak a cykle
 +
 + no_cycle();​
 + shared_cycle();​
 + weak_cycle();​
 + shared_and_weak();​
 +
 + // ==========================================================
 + //  GŁÓWNY POWÓD UŻYWANIA SMART_PTRów
 + //    komfort operatora "​new"​
 + //    z bezpieczeństwem zmiennych automatycznych
 + // ==========================================================
 + try {
 + comfort_test();​
 + } catch (...) {
 + cout << "​Caught!"​ << endl;
 + }
 +
 + // ==========================================================
 + // Test enable_shared_from_this<>​
 + boost::​shared_ptr<​WithSharing>​ ws(new WithSharing);​
 + with_sharing_test(*ws);​
 +
 + // ==========================================================
 + // std::​auto_ptr
 + auto_ptr_demo();​
 +
 + // ==========================================================
 + // Intrusive test
 + test_intrusive_ptr();​
 +
 + return 0;
 +}
 </​code>​ </​code>​
smart_ptr.txt · ostatnio zmienione: 2008/10/23 11:03 przez rnowak2