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
smart_ptr [2008/04/16 01:48]
wodny
smart_ptr [2008/10/23 11:03]
rnowak2
Linia 1: Linia 1:
-{{libs:​smart_ptr:​smart_ptr_iso.cpp|}}+{{smart_ptr_latin2.cpp|}}
 <code cpp> <code cpp>
-/*+*
  * Autor: Marcin Szewczyk, 198370  * Autor: Marcin Szewczyk, 198370
  *  *
Linia 24: Linia 24:
  ​* ​ nie został opisany typ shared_array,​ ponieważ nie wnosi nic nowego do   ​* ​ nie został opisany typ shared_array,​ ponieważ nie wnosi nic nowego do 
  ​* ​ omawianych tu zagadnień  ​* ​ omawianych tu zagadnień
 + *
 + ​* ​ Changelog:
 + ​* ​ 2008.10.18 ​ W końcu poprawiłem mały wyciek pamięci w miejscu, w którym
 + ​* ​             nie użyłem smart_ptr - o ironio!
 + *
 + ​* ​ Dobre rady:
 + ​* ​ W tym dokumencie prezentowany jest wyciek pamięci w przypadku cykli
 + ​* ​ budowanych na shared_ptr i jego brak w przypadku cykli budowanych na
 + ​* ​ weak_ptr. Można uzyskać dobrą wizualizację zagadnienia przy pomocy
 + ​* ​ aplikacji valgrind,
 + ​* ​ Proponowany sposób użycia:
 + ​* ​ valgrind --leak-check=full ./smart_ptr > /dev/null
 + ​* ​ Efekt:
 + ​* ​     114 (12 direct, 102 indirect) bytes in 1 blocks are definitely lost in loss
 +record 3 of 5
 + ​* ​       at 0x4023294: operator new(unsigned) (vg_replace_malloc.c:​224)
 + ​* ​       by 0x8049AAE: shared_cycle() (smart_ptr.cpp:​474)
 + ​* ​       by 0x804B5C6: main (smart_ptr.cpp:​608)
 + *
 + ​* ​ Support:
 + ​* ​     wodny@thlen.pl <- usuń h
  */  */
  
Linia 42: Linia 63:
  
 class Harry { class Harry {
- public: +        ​public: 
- Harry(const char* = NULL); +                Harry(const char* = NULL); 
- ~Harry();+                ~Harry();
  
- void hello(); +                ​void hello(); 
- private: +        private: 
- char *name;+                char *name;
 }; };
  
  
 class Betty : public Harry { class Betty : public Harry {
- public: +        ​public: 
- Betty(); +                Betty(); 
- ~Betty();+                ~Betty();
 }; };
  
Linia 61: Linia 82:
  
 Harry::​Harry(const char *name_) { Harry::​Harry(const char *name_) {
- name = name_ ? strdup(name_) : NULL; +        ​name = name_ ? strdup(name_) : NULL; 
- printf("​-- Constructing Harry (%s)\n",​ name);+        printf("​-- Constructing Harry (%s)\n",​ name);
 } }
  
 Harry::​~Harry() { Harry::​~Harry() {
- printf("​-- Deconstructing Harry (%s)\n",​ name);+        ​printf("​-- Deconstructing Harry (%s)\n", ​name); 
 +        free(name);
 } }
  
 void Harry::​hello() { void Harry::​hello() {
- printf("​-- Harry \"​%s\"​ says hello\n",​ name);+        ​printf("​-- Harry \"​%s\"​ says hello\n",​ name);
 } }
  
Linia 76: Linia 98:
  
 Betty::​Betty() { Betty::​Betty() {
- printf("​---- Constructing Betty\n"​);​+        ​printf("​---- Constructing Betty\n"​);​
 } }
  
 Betty::​~Betty() { Betty::​~Betty() {
- printf("​---- Deconstructing Betty\n"​);​+        ​printf("​---- Deconstructing Betty\n"​);​
 } }
  
Linia 90: Linia 112:
  
 class RingNode { class RingNode {
- public: +        ​public: 
- RingNode(const char*, const boost::​shared_ptr<​RingNode>&​);​ +                RingNode(const char*, const boost::​shared_ptr<​RingNode>&​);​ 
- ~RingNode();​ +                ~RingNode();​ 
- void connect(const boost::​shared_ptr<​RingNode>&​);​ +                void connect(const boost::​shared_ptr<​RingNode>&​);​ 
- const char* get_name();​ +                const char* get_name();​ 
- const boost::​shared_ptr<​RingNode>&​ get_node();​ +                const boost::​shared_ptr<​RingNode>&​ get_node();​ 
- private: +        private: 
- boost::​shared_ptr<​RingNode>​ node; +                boost::​shared_ptr<​RingNode>​ node; 
- char* name;+                char* name;
 }; };
  
-RingNode::​RingNode(const char* name_, const boost::​shared_ptr<​RingNode>&​ node_) : node(node_){ +RingNode::​RingNode(const char* name_, const boost::​shared_ptr<​RingNode>&​ node_) : 
- name = name_ ? strdup(name_) : NULL; +node(node_) { 
- printf("​++ Constructing RingNode (%s)\n",​ name);+        name = name_ ? strdup(name_) : NULL; 
 +        printf("​++ Constructing RingNode (%s)\n",​ name);
 } }
  
 RingNode::​~RingNode() { RingNode::​~RingNode() {
- printf("​++ Deconstructing RingNode (%s)\n",​ name);+        ​printf("​++ Deconstructing RingNode (%s)\n", ​name); 
 +        free(name);
 } }
  
 void RingNode::​connect(const boost::​shared_ptr<​RingNode>&​ node_) { void RingNode::​connect(const boost::​shared_ptr<​RingNode>&​ node_) {
- node = node_;+        ​node = node_;
 } }
  
 const char* RingNode::​get_name() { const char* RingNode::​get_name() {
- return name;+        ​return name;
 } }
  
 const boost::​shared_ptr<​RingNode>&​ RingNode::​get_node() { const boost::​shared_ptr<​RingNode>&​ RingNode::​get_node() {
- return node;+        ​return node;
 } }
  
Linia 126: Linia 150:
  
 class WeakRingNode { class WeakRingNode {
- public: +        ​public: 
- WeakRingNode(const char*, const boost::​shared_ptr<​WeakRingNode>&​);​ +                WeakRingNode(const char*, const boost::​shared_ptr<​WeakRingNode>&​);​ 
- ~WeakRingNode();​ +                ~WeakRingNode();​ 
- void connect(const boost::​shared_ptr<​WeakRingNode>&​);​ +                void connect(const boost::​shared_ptr<​WeakRingNode>&​);​ 
- const char* get_name();​ +                const char* get_name();​ 
- const boost::​shared_ptr<​WeakRingNode>​ get_node();​ +                const boost::​shared_ptr<​WeakRingNode>​ get_node();​ 
- private: +        private: 
- boost::​weak_ptr<​WeakRingNode>​ node; +                boost::​weak_ptr<​WeakRingNode>​ node; 
- char* name;+                char* name;
 }; };
  
-WeakRingNode::​WeakRingNode(const char* name_, const boost::​shared_ptr<​WeakRingNode>&​ node_) : node(node_) { +WeakRingNode::​WeakRingNode(const char* name_, const boost::​shared_ptr<​WeakRingNode>&​ 
- name = name_ ? strdup(name_) : NULL; +node_) : node(node_) { 
- printf("​++ Constructing RingNode (%s)\n",​ name);+        name = name_ ? strdup(name_) : NULL; 
 +        printf("​++ Constructing RingNode (%s)\n",​ name);
 } }
  
 WeakRingNode::​~WeakRingNode() { WeakRingNode::​~WeakRingNode() {
- printf("​++ Deconstructing RingNode (%s)\n",​ name);+        ​printf("​++ Deconstructing RingNode (%s)\n", ​name); 
 +        free(name);
 } }
  
 void WeakRingNode::​connect(const boost::​shared_ptr<​WeakRingNode>&​ node_) { void WeakRingNode::​connect(const boost::​shared_ptr<​WeakRingNode>&​ node_) {
- node = node_;+        ​node = node_;
 } }
  
 const char* WeakRingNode::​get_name() { const char* WeakRingNode::​get_name() {
- return name;+        ​return name;
 } }
  
 const boost::​shared_ptr<​WeakRingNode>​ WeakRingNode::​get_node() { const boost::​shared_ptr<​WeakRingNode>​ WeakRingNode::​get_node() {
- return node.lock();​+        ​return node.lock();​
 } }
  
Linia 165: Linia 191:
  
 class Intruded { class Intruded {
- public: +        ​public: 
- Intruded();​ +                Intruded();​ 
- ~Intruded();​ +                ~Intruded();​ 
- private: +        private: 
- int counter;+                int counter;
  
- friend void intrusive_ptr_add_ref(Intruded *const); +                ​friend void intrusive_ptr_add_ref(Intruded *const); 
- friend void intrusive_ptr_release(Intruded *const);+                friend void intrusive_ptr_release(Intruded *const);
 }; };
  
Linia 181: Linia 207:
  
 Intruded::​Intruded() : counter(0) { Intruded::​Intruded() : counter(0) {
- printf("​%% Creating Intruded\n"​);​+        ​printf("​%% Creating Intruded\n"​);​
 } }
  
 Intruded::​~Intruded() { Intruded::​~Intruded() {
- printf("​%% Destroying Intruded\n"​);​+        ​printf("​%% Destroying Intruded\n"​);​
 } }
  
Linia 194: Linia 220:
  
 void intrusive_ptr_add_ref(Intruded *const p) { void intrusive_ptr_add_ref(Intruded *const p) {
- printf("​%% Added. Now: %d\n", ++(p->​counter));​+        ​printf("​%% Added. Now: %d\n", ++(p->​counter));​
 } }
  
 void intrusive_ptr_release(Intruded *const p) { void intrusive_ptr_release(Intruded *const p) {
- printf("​%% Removed. Now: %d\n", --(p->​counter));​ +        ​printf("​%% Removed. Now: %d\n", --(p->​counter));​ 
- if(!p->​counter) { +        if(!p->​counter) { 
- printf("​%% Deleting Intruded because of count == 0...\n"​);​ +                printf("​%% Deleting Intruded because of count == 0...\n"​);​ 
- delete p; +                delete p; 
- }+        }
 } }
  
Linia 214: Linia 240:
 class WithSharing : public boost::​enable_shared_from_this<​WithSharing>​ { class WithSharing : public boost::​enable_shared_from_this<​WithSharing>​ {
 public: public:
- boost::​shared_ptr<​WithSharing>​ get_shared() { +        ​boost::​shared_ptr<​WithSharing>​ get_shared() { 
- return shared_from_this();​ +                return shared_from_this();​ 
- }+        }
 }; };
  
Linia 232: Linia 258:
  
 void header(const char* label) { void header(const char* label) {
- char* bar = strdup(label);​ +        ​char* bar = strdup(label);​ 
- memset(bar,​ '​=',​ strlen(bar));​ +        cout << endl << label << endl; 
- cout << endl << label << endl << bar << endl;+        ​memset(bar, '​=',​ strlen(bar));​ 
 +        cout << bar << endl
 +        free(bar);
 } }
  
Linia 242: Linia 270:
 // Funkcja jest wywoływana,​ ale szkodliwy fragment jest wykomentowany // Funkcja jest wywoływana,​ ale szkodliwy fragment jest wykomentowany
 void play_dirty_harry() { void play_dirty_harry() {
- header("​Dirty Harry - czego ze wskaznikami robic nie wolno"​);​+        ​header("​Dirty Harry - czego ze wskaznikami robic nie wolno"​);​
  
- Harry* tmp_harry;​ +        ​Harry* tmp_harry;​ 
- boost::​scoped_ptr<​Harry>​ harry(tmp_harry = new Harry("​Simple Class Harry"​));​+        boost::​scoped_ptr<​Harry>​ harry(tmp_harry = new Harry("​Simple Class Harry"​));​
  
- //​boost::​scoped_ptr<​Harry>​ harry2(tmp_harry);​ +        ​//​boost::​scoped_ptr<​Harry>​ harry2(tmp_harry);​ 
- // Nielegalne - dwa scoped_ptr, każdy z liczbą odwołań = 1 +        // Nielegalne - dwa scoped_ptr, każdy z liczbą odwołań = 1 
- // Podczas destrukcji dwóch scoped_ptr dochodzi dwa razy do próby destrukcji  +        // 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  +        // jednego obiektu klasy Harry. Lepiej przedstawi to shared_ptr, który pojawi  
- // się poniżej+        // się poniżej
  
- //​boost::​scoped_ptr<​Harry>​ harry_b(harry);​ +        ​//​boost::​scoped_ptr<​Harry>​ harry_b(harry);​ 
- // Kopiowanie scoped_ptr jest zakazane (konst. kopiujący w sekcji private) +        // Kopiowanie scoped_ptr jest zakazane (konst. kopiujący w sekcji private) 
- //​boost::​scoped_ptr<​Harry>​ harry_c; +        //​boost::​scoped_ptr<​Harry>​ harry_c; 
- //harry_c = harry; +        //harry_c = harry; 
- // Analogiczna uwaga dotyczy operatora przypisania+        // Analogiczna uwaga dotyczy operatora przypisania
  
 } }
  
 void play_nice_harry() { void play_nice_harry() {
- header("​play_nice_harry - scoped_ptr jak zmienna automatyczna"​);​ +        ​header("​play_nice_harry - scoped_ptr jak zmienna automatyczna"​);​ 
- // Jakieś tam zadania +        // Jakieś tam zadania 
- // ...+        // ...
  
- // Tutaj proste zastosowanie - scoped_ptr zachowuje się jak zmienna  +        ​// Tutaj proste zastosowanie - scoped_ptr zachowuje się jak zmienna  
- // automatyczna. Po wyjściu poza zasięg, scoped_ptr niszczy siebie, a  +        // automatyczna. Po wyjściu poza zasięg, scoped_ptr niszczy siebie, a  
- // wcześniej związany z nim obiekt. +        // wcześniej związany z nim obiekt. 
- // +        // 
- // Stąd nazwa - scoped - czyli dot. zasięgu. +        // Stąd nazwa - scoped - czyli dot. zasięgu. 
- // Nawiązuje to do pomysłu "​resource acquisition is initialization"​. Zasoby  +        // Nawiązuje to do pomysłu "​resource acquisition is initialization"​. Zasoby  
- // są zajmowane w momencie inicjalizacji i, co ważniejsze,​ zwalniane podczas  +        // są zajmowane w momencie inicjalizacji i, co ważniejsze,​ zwalniane podczas  
- // "​odinicjowania",​ czyli destrukcji po wyjściu poza zasięg.+        // "​odinicjowania",​ czyli destrukcji po wyjściu poza zasięg.
  
- boost::​scoped_ptr<​Harry>​ harry3(new Harry("​Harry3"​));​ +        ​boost::​scoped_ptr<​Harry>​ harry3(new Harry("​Harry3"​));​ 
- harry3->​hello();​+        harry3->​hello();​
  
- Harry harry4("​Harry4"​);​ +        ​Harry harry4("​Harry4"​);​ 
- harry4.hello();​+        harry4.hello();​
  
 } }
  
 void play_nice_harry3() { void play_nice_harry3() {
- // Jednak nie zawsze wystarcza nam zmienna automatyczna. Ciekawsze jest  +        ​// Jednak nie zawsze wystarcza nam zmienna automatyczna. Ciekawsze jest  
- // dynamiczne powoływanie obiektów do życia operatorem "​new"​.+        // dynamiczne powoływanie obiektów do życia operatorem "​new"​.
  
- header("​play_nice_harry3 - operator \"​new\"​ bez potrzeby wywolania delete"​);​ +        ​header("​play_nice_harry3 - operator \"​new\"​ bez potrzeby wywolania delete"​);​ 
- boost::​scoped_ptr<​Harry>​ harry7;+        boost::​scoped_ptr<​Harry>​ harry7;
  
- // +        ​// 
- // Coś tam do roboty... +        // Coś tam do roboty... 
- bool needHarry = true; +        bool needHarry = true; 
- // Coś tam do roboty... +        // Coś tam do roboty... 
- //+        //
  
- if(needHarry)+        ​if(needHarry) 
 +                harry7.reset(new Harry("​Harry7"​));​
  
- harry7.reset(new Harry("​Harry7"​));​+        // 
 +        // Coś tam do roboty... 
 +        //
  
- // +        if(harry7) { 
- // Coś tam do roboty... +                ​printf("​-- Stwierdzlismy,​ ze harry7 sie przyda - wykonajmy na nim operacje\n"​);​ 
- //+                ​// Operacje na Harrym... 
 +        }
  
- if(harry7) { +        ​// Normalnie w tym miejscu przydałoby się wywołanie delete na zwykłym  
- printf("​-- Stwierdzlismy,​ ze harry7 sie przyda - wykonajmy na nim operacje\n"​);​ +        // wskaźniku. Ponieważ jednak nasz inteligenty wskaźnik jest zmienną  
- // Operacje na Harrym... +        // automatyczną,​ sam usunie siebie i skojarzony obiekt
-+
- +
- // 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) { void comfort_test() throw(exception) {
- header("​Comfort test - shared_ptr jak zm. auto.; auto. usuwanie, gdy rzucany jest wyjatek"​);​ +        ​header("​Comfort test - shared_ptr jak zm. auto.; auto. usuwanie, gdy rzucany jest 
- boost::​shared_ptr<​Harry>​ h1; +wyjatek"​);​ 
- boost::​shared_ptr<​Harry>​ h2;+        boost::​shared_ptr<​Harry>​ h1; 
 +        boost::​shared_ptr<​Harry>​ h2;
  
- // Coś tam...+        ​// Coś tam...
  
- // Potrzebujemy Harry'​ego +        ​// Potrzebujemy Harry'​ego 
- h1.reset(new Harry("​Potter"​));​ +        h1.reset(new Harry("​Potter"​));​ 
- h2.reset(new Harry("​Callahan"​));​ +        h2.reset(new Harry("​Callahan"​));​ 
- cout << "​Callahan count: " << h2.use_count() << endl; +        cout << "​Callahan count: " << h2.use_count() << endl; 
- h1 = h2; +        h1 = h2; 
- cout << "​Callahan zjadl Pottera, count: " << h2.use_count() << endl; +        cout << "​Callahan zjadl Pottera, count: " << h2.use_count() << endl; 
- cout << "h1: "; +        cout << "h1: "; 
- h1->​hello();​ +                h1->​hello();​ 
- cout << "h2: "; +        cout << "h2: "; 
- h2->​hello();​+                h2->​hello();​
  
- // Go ahead, make my day. +        ​// Go ahead, make my day. 
- //   ​Rzucamy wyjątek +        //   ​Rzucamy wyjątek 
- cout << "​Throwing an exception .44" << endl; +        cout << "​Throwing an exception .44" << endl; 
- throw exception();​+        throw exception();​
 } }
  
 // Prezentacja,​ jak zachowują się intrusive_ptr // Prezentacja,​ jak zachowują się intrusive_ptr
 void test_intrusive_ptr() { void test_intrusive_ptr() {
- header("​test_intrusive_ptr"​);​ +        ​header("​test_intrusive_ptr"​);​ 
- boost::​intrusive_ptr<​Intruded>​ i1(new Intruded);+        boost::​intrusive_ptr<​Intruded>​ i1(new Intruded);
 } }
  
 // Ciekawostka związana z shared_ptr // Ciekawostka związana z shared_ptr
-// Różnica, między tym, co deklarujemy jako klasę dla szablony ​shared_ptr, a +// Różnica, między tym, co deklarujemy jako klasę dla szablonu ​shared_ptr, a 
 // klasą parametru przekazywanego w konstruktorze. Jakie nieoczywiste zdarzenie ​ // klasą parametru przekazywanego w konstruktorze. Jakie nieoczywiste zdarzenie ​
 // może wystąpić, gdy destruktory klas są niewirtualne. // może wystąpić, gdy destruktory klas są niewirtualne.
  
 void non_virt_diffs() { void non_virt_diffs() {
- header("​Niewirtualny destruktor. Roznice miedzy zwyklym wskaznikiem a shared_ptr"​);​ +        ​header("​Niewirtualny destruktor. Roznice miedzy zwyklym wskaznikiem a shared_ptr"​);​ 
- // Destructor nie jest wirtualny, stąd Betty nie jest niszczona +        // Destructor nie jest wirtualny, stąd Betty nie jest niszczona 
-+        
- cout << "​Zwykly Harry-wskaznik na Betty" << endl; +                cout << "​Zwykly Harry-wskaznik na Betty" << endl; 
- Harry *hb = new Betty; +                Harry *hb = new Betty; 
- delete hb; +                delete hb; 
-+        
-  +         
- // Nieco inaczej sprawa się przestawia dla shared_ptr +        // Nieco inaczej sprawa się przestawia dla shared_ptr 
-+        
- cout << endl << "​Betty-wskaznik na Betty w Harry-szablonie"​ << endl; +                cout << endl << "​Betty-wskaznik na Betty w Harry-szablonie"​ << endl; 
- boost::​shared_ptr<​Harry>​ b1(new Betty); +                boost::​shared_ptr<​Harry>​ b1(new Betty); 
- // shared_ptr pamięta rzeczywisty typ wskaźnika przekazywanego w  +                // shared_ptr pamięta rzeczywisty typ wskaźnika przekazywanego w  
- // parametrze. W związku z tym używa destruktora dla tego typu (Betty)  +                // parametrze. W związku z tym używa destruktora dla tego typu (Betty)  
- // zamiast typu deklarowanego w szablonie (Harry) +                // zamiast typu deklarowanego w szablonie (Harry) 
- //  > przykładowa implementacja mechanizmu:​ +                //  > przykładowa implementacja mechanizmu:​ 
- //  > http://​wodny.org/​download/​smart_ptr/​template_memory.cpp +                //  > http://​wodny.org/​download/​smart_ptr/​template_memory.cpp 
-+        
-  +         
-+        
- cout << endl << "​Harry-wskaznik na Betty w Harry-szablonie"​ << endl; +                cout << endl << "​Harry-wskaznik na Betty w Harry-szablonie"​ << endl; 
- Harry *b3 = new Betty; +                Harry *b3 = new Betty; 
- boost::​shared_ptr<​Harry>​ b2(b3); +                boost::​shared_ptr<​Harry>​ b2(b3); 
- // Tutaj shared_ptr nie ma okazji poznać prawdziwego typu obiektu. ​  +                // Tutaj shared_ptr nie ma okazji poznać prawdziwego typu obiektu. ​  
- // Traktuje go jak Harry'​ego. Dla poprawnego działania, tu destruktor już  +                // Traktuje go jak Harry'​ego. Dla poprawnego działania, tu destruktor już  
- // musi być wirtualny. +                // musi być wirtualny. 
- }+        }
  
 } }
  
 void play_scoped_array() { void play_scoped_array() {
- // Prosty przykład, że inteligentne wskaźniki z dopiskiem _array służą do  +        ​// 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  +        // 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,  +        // związane z obostrzeniem,​ że delete stosujemy dla pojedynczego obiektu,  
- // delete[] dla tablic. Inteligenty wskaźnik nie posiadając informacji o  +        // delete[] dla tablic. Inteligenty wskaźnik nie posiadając informacji o  
- // naturze przekazanego wskaźnika źle zarządzałby pamięcią. +        // naturze przekazanego wskaźnika źle zarządzałby pamięcią. 
- header("​Zabawy ze scoped_array"​);​ +        header("​Zabawy ze scoped_array"​);​ 
- boost::​scoped_array<​Harry>​ harry_a1(new Harry[3]);+        boost::​scoped_array<​Harry>​ harry_a1(new Harry[3]);
 } }
  
 void general_use() { void general_use() {
- header("​Ogolny sposob uzycia shared_ptr"​);​+        ​header("​Ogolny sposob uzycia shared_ptr"​);​
  
- Harry *hp1 = NULL; +        ​Harry *hp1 = NULL; 
- boost::​shared_ptr<​Harry>​ harry_sp1(hp1 = new Harry("​Shared Harry1"​));​ +        boost::​shared_ptr<​Harry>​ harry_sp1(hp1 = new Harry("​Shared Harry1"​));​ 
- cout << "​harry_sp1.use_count:​ " << harry_sp1.use_count() << endl; +        cout << "​harry_sp1.use_count:​ " << harry_sp1.use_count() << endl; 
- //​boost::​shared_ptr<​Harry>​ harry_sp2(hp1);​ +        //​boost::​shared_ptr<​Harry>​ harry_sp2(hp1);​ 
- // Taka konstrukcja spowoduje błąd. Dwa shared_ptr będą próbowały usunąć dwa  +        // Taka konstrukcja spowoduje błąd. Dwa shared_ptr będą próbowały usunąć dwa  
- // razy ten sam obiekt podczas własnej destrukcji. +        // razy ten sam obiekt podczas własnej destrukcji. 
- // +        // 
- // Istotne jest, by zauważyć, że shared_ptr nie ma jakiejś ukrytej tablicy  +        // 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  +        // asocjacyjnej (trzymającej się np. wzorca Singleton), która pozwalałaby mu  
- // stwierdzać,​ którymi wskaźnikami już się opiekuje. +        // stwierdzać,​ którymi wskaźnikami już się opiekuje. 
- // Poinformowanie o tym, że kolejny shared_ptr chce również odnosić się do  +        // Poinformowanie o tym, że kolejny shared_ptr chce również odnosić się do  
- // danego zwykłego wskaźnika następuje przez wykonanie konstruktora  +        // danego zwykłego wskaźnika następuje przez wykonanie konstruktora  
- // kopiującego (opcjonalnie operatora przypisania). Od tej pory każdy z  +        // 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,  +        // 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  +        // drugi inteligenty wskaźnik dowie się o tym zdarzeniu i zdekrementuje  
- // własny licznik odwołań +        // własny licznik odwołań 
- // (Mowa jest tu o logice działania, nie rzeczywistej implementacji  +        // (Mowa jest tu o logice działania, nie rzeczywistej implementacji  
- // inteligentnego wskaźnika). +        // inteligentnego wskaźnika). 
- cout << "Czas, by podzielic sie zasobem"​ << endl; +        cout << "Czas, by podzielic sie zasobem"​ << endl; 
- boost::​shared_ptr<​Harry>​ harry_sp2(harry_sp1);​ +        boost::​shared_ptr<​Harry>​ harry_sp2(harry_sp1);​ 
- boost::​shared_ptr<​Harry>​ harry_sp3;​ +        boost::​shared_ptr<​Harry>​ harry_sp3;​ 
- harry_sp3 = harry_sp2;​ +        harry_sp3 = harry_sp2;​ 
- cout << "​harry_sp1.use_count:​ " << harry_sp1.use_count() << endl; +        cout << "​harry_sp1.use_count:​ " << harry_sp1.use_count() << endl; 
- cout << "​harry_sp2.use_count:​ " << harry_sp2.use_count() << endl; +        cout << "​harry_sp2.use_count:​ " << harry_sp2.use_count() << endl; 
- cout << "​harry_sp3.use_count:​ " << harry_sp3.use_count() << endl;+        cout << "​harry_sp3.use_count:​ " << harry_sp3.use_count() << endl;
  
 } }
  
 SharedHarryVector* get_harries() { SharedHarryVector* get_harries() {
- // Shared_ptr a kontenery +        ​// Shared_ptr a kontenery 
- // (scoped_ptr nie może zostać użyty do takich zastosowań - nie da się  +        // (scoped_ptr nie może zostać użyty do takich zastosowań - nie da się  
- // skopiować kontenerowi,​ poza tym jego przeznaczenie jest inne) +        // skopiować kontenerowi,​ poza tym jego przeznaczenie jest inne) 
- header("​Wektor (vector) z Harrych - uzycie shared_ptr w kontenerach STL");+        header("​Wektor (vector) z Harrych - uzycie shared_ptr w kontenerach STL");
  
- SharedHarryVector *vect = new SharedHarryVector();​ +        ​SharedHarryVector *vect = new SharedHarryVector();​ 
- boost::​shared_ptr<​Harry>​ h; +        boost::​shared_ptr<​Harry>​ h; 
- for(int i = 0; i < 4; ++i) { +        for(int i = 0; i < 4; ++i) { 
- h.reset(new Harry("​Vector Harry"​));​ +                h.reset(new Harry("​Vector Harry"​));​ 
- cout << "Ilosc Harry'​ego przed wlozeniem do wektora: " << h.use_count() << endl; +                cout << "Ilosc Harry'​ego przed wlozeniem do wektora: " << h.use_count() << endl; 
- vect->​push_back(h);​ +                vect->​push_back(h);​ 
- cout << "Po wlozeniu: " << h.use_count() << endl; +                cout << "Po wlozeniu: " << h.use_count() << endl; 
-+        
- return vect;+        return vect;
 } }
  
 void stl_container() { void stl_container() {
- // W nawiązaniu do powyższej funkcji +        ​// W nawiązaniu do powyższej funkcji 
- boost::​shared_ptr<​ SharedHarryVector > harry_vector(get_harries());​ +        boost::​shared_ptr<​ SharedHarryVector > harry_vector(get_harries());​ 
- cout << "​Liczność jednego z wektorowych Harrych: " << harry_vector->​front().use_count() << endl << endl;+        cout << "​Liczność jednego z wektorowych Harrych: " << 
 +harry_vector->​front().use_count() << endl << endl;
 } }
  
 void no_cycle() { void no_cycle() {
- header("​Bez cyklu"​);​ +        ​header("​Bez cyklu"​);​ 
- // Bez cyklu +        // Bez cyklu 
- boost::​shared_ptr<​RingNode>​ R3(new RingNode("​RingNode3",​ boost::​shared_ptr<​RingNode>​((RingNode*)NULL)));​ +        boost::​shared_ptr<​RingNode>​ R3(new RingNode("​RingNode3",​ 
- boost::​shared_ptr<​RingNode>​ R4(new RingNode("​RingNode4",​ boost::​shared_ptr<​RingNode>​(R3)));​ +boost::​shared_ptr<​RingNode>​((RingNode*)NULL)));​ 
- cout << "R3 (" << R4->​get_name() << ") with count " << R3.use_count() << endl; +        boost::​shared_ptr<​RingNode>​ R4(new RingNode("​RingNode4",​ 
- cout << "R4 (" << R4->​get_name() << ") with count " << R4.use_count() << " connected to " << R4->​get_node()->​get_name() << endl; +boost::​shared_ptr<​RingNode>​(R3)));​ 
- // Wszystkie węzły ulegną zniszczeniu jak powinny+        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() { void shared_cycle() {
- header("​Cykl na shared_ptr"​);​ +        ​header("​Cykl na shared_ptr"​);​ 
- // Większy cykl, choć uzyskany tylko pośrednio, powoduje, że węzły nie  +        // 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 +        // 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>​ R7(new RingNode("​RingNode7",​ 
- boost::​shared_ptr<​RingNode>​ R8(new RingNode("​RingNode8",​ boost::​shared_ptr<​RingNode>​(R7)));​ +boost::​shared_ptr<​RingNode>​((RingNode*)NULL)));​ 
- boost::​shared_ptr<​RingNode>​ R9(new RingNode("​RingNode9",​ boost::​shared_ptr<​RingNode>​(R8)));​ +        boost::​shared_ptr<​RingNode>​ R8(new RingNode("​RingNode8",​ 
- R7->​connect(R9);​ +boost::​shared_ptr<​RingNode>​(R7)));​ 
- cout << "R7 (" << R7->​get_name() << ") with count " << R7.use_count() << " connected to " << R7->​get_node()->​get_name() << endl; +        boost::​shared_ptr<​RingNode>​ R9(new RingNode("​RingNode9",​ 
- cout << "R8 (" << R8->​get_name() << ") with count " << R8.use_count() << " connected to " << R8->​get_node()->​get_name() << endl; +boost::​shared_ptr<​RingNode>​(R8)));​ 
- cout << "R9 (" << R9->​get_name() << ") with count " << R9.use_count() << " connected to " << R9->​get_node()->​get_name() << endl;+        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"<​--------------------.+    R7-->"​R7"<​--------node--------.
            ​| ​                     |            ​| ​                     |
            ​*--node-->"​R8"<​--R8 ​   |            ​*--node-->"​R8"<​--R8 ​   |
                        ​| ​         |                        ​| ​         |
                        ​*--node-->"​R9"<​--R9                        ​*--node-->"​R9"<​--R9
- */+        ​*/
 } }
  
 void weak_cycle() { void weak_cycle() {
- header("​Cykl na weak_ptr"​);​ +        ​header("​Cykl na weak_ptr"​);​ 
- // "​Słaby"​ cykl oparty o 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>​ R5(new WeakRingNode("​WeakRingNode5",​ 
- boost::​shared_ptr<​WeakRingNode>​ R6(new WeakRingNode("​WeakRingNode6",​ boost::​shared_ptr<​WeakRingNode>​(R5)));​ +boost::​shared_ptr<​WeakRingNode>​((WeakRingNode*)NULL)));​ 
- R5->​connect(R6);​ +        boost::​shared_ptr<​WeakRingNode>​ R6(new WeakRingNode("​WeakRingNode6",​ 
- boost::​weak_ptr<​WeakRingNode>​ Wtmp1(R5);​ +boost::​shared_ptr<​WeakRingNode>​(R5)));​ 
- boost::​weak_ptr<​WeakRingNode>​ Wtmp2(R6);​ +        R5->​connect(R6);​ 
- // Jak można zauważyć, weak_ptr nie zwiększa licznika odwołań do obiektu,  +        boost::​weak_ptr<​WeakRingNode>​ Wtmp1(R5);​ 
- // którego dotyczy, ani nie usuwa obiektu, gdy wielkość ta spadnie do zera.   +        boost::​weak_ptr<​WeakRingNode>​ Wtmp2(R6);​ 
- // Obiekt, do którego się odwołuje może zostać usunięty "bez jego wiedzy"​. ​  +        // Jak można zauważyć, weak_ptr nie zwiększa licznika odwołań do obiektu,  
- // Dlatego właśnie współpracuje z shared_ptr. +        // którego dotyczy, ani nie usuwa obiektu, gdy wielkość ta spadnie do zera.   
- cout << "R5 (" << R5->​get_name() << ") with count " << R5.use_count() << " connected to " << R5->​get_node()->​get_name() << endl; +        // Obiekt, do którego się odwołuje może zostać usunięty "bez jego wiedzy"​. ​  
- cout << "R6 (" << R6->​get_name() << ") with count " << R6.use_count() << " connected to " << R6->​get_node()->​get_name() << endl; +        // Dlatego właśnie współpracuje z shared_ptr. 
- // Poprzez funkcję weak_ptr.lock(),​ która użyta jest w get_node(), weak_ptr  +        cout << "R5 (" << R5->​get_name() << ") with count " << R5.use_count() << " 
- // gwarantuje nam, że zostanie wykonana dodatkowa kopia, a shared_ptr zajmie  +connected to " << R5->​get_node()->​get_name() << endl; 
- // się zwiększeniem licznika odwołań, by obiekt nie zniknął podczas  +        cout << "R6 (" << R6->​get_name() << ") with count " << R6.use_count() << " 
- // wykonywania na nim operacji. +connected to " << R6->​get_node()->​get_name() << endl; 
- // Jeśli obiekt zdążył zniknąć już wcześniej, podczas tworzenia shared_ptr z  +        // Poprzez funkcję weak_ptr.lock(),​ która użyta jest w get_node(), weak_ptr  
- // weak_ptr dostaniemy wyjątek bad_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() { void shared_and_weak() {
- header("​Relacja miedzy shared_ptr i weak_ptr"​);​+        ​header("​Relacja miedzy shared_ptr i weak_ptr"​);​
  
- cout << "​Oryginalny shared_ptr:"​ << endl; +        ​cout << "​Oryginalny shared_ptr:"​ << endl; 
- boost::​shared_ptr<​Harry>​ shared1(new Harry); +        boost::​shared_ptr<​Harry>​ shared1(new Harry); 
- cout << "​shared1.count:​ " << shared1.use_count() << endl;+        cout << "​shared1.count:​ " << shared1.use_count() << endl;
  
- cout << "​weak_ptr z shared_ptr:"​ << endl; +        ​cout << "​weak_ptr z shared_ptr:"​ << endl; 
- boost::​weak_ptr<​Harry>​ weak1(shared1);​ +        boost::​weak_ptr<​Harry>​ weak1(shared1);​ 
- cout << "​shared1.count:​ " << shared1.use_count() << endl; +        cout << "​shared1.count:​ " << shared1.use_count() << endl; 
- cout << "​weak1.count ​ : " << weak1.use_count() << endl;+        cout << "​weak1.count ​ : " << weak1.use_count() << endl;
  
- cout << "​shared_ptr z weak_ptr (z shared_ptr)"​ << endl; +        ​cout << "​shared_ptr z weak_ptr (z shared_ptr)"​ << endl; 
- boost::​shared_ptr<​Harry>​ shared2(weak1);​ +        boost::​shared_ptr<​Harry>​ shared2(weak1);​ 
- cout << "​shared1.count:​ " << shared1.use_count() << endl; +        cout << "​shared1.count:​ " << shared1.use_count() << endl; 
- cout << "​weak1.count ​ : " << weak1.use_count() << endl; +        cout << "​weak1.count ​ : " << weak1.use_count() << endl; 
- cout << "​shared2.count:​ " << shared2.use_count() << endl;+        cout << "​shared2.count:​ " << shared2.use_count() << endl;
 } }
  
 void with_sharing_test(WithSharing&​ ws) { void with_sharing_test(WithSharing&​ ws) {
- header("​Test enable_shared_from_this<>"​);​+        ​header("​Test enable_shared_from_this<>"​);​
  
- boost::​shared_ptr<​WithSharing>​ ws_a(ws.get_shared());​ +        ​boost::​shared_ptr<​WithSharing>​ ws_a(ws.get_shared());​ 
- cout << "Drugi udzial, use_count: " << ws_a.use_count() << endl; +        cout << "Drugi udzial, use_count: " << ws_a.use_count() << endl; 
- /*  . +        /*  . 
-  * /|\ +         ​* /|\ 
-  *  | +         ​*  | 
-  * ------------------------------------------------- +         ​* ------------------------------------------------- 
-  * dwa niezależne fragmenty kodu, np. dwa wątki +         ​* dwa niezależne fragmenty kodu, np. dwa wątki 
-  * ------------------------------------------------- +         ​* ------------------------------------------------- 
-  *  | +         ​*  | 
-  * \|/ +         ​* \|/ 
-  *  ' +         ​*  ' 
-  */ +         ​*/ 
- boost::​shared_ptr<​WithSharing>​ ws_b(ws.get_shared());​ +        boost::​shared_ptr<​WithSharing>​ ws_b(ws.get_shared());​ 
- cout << "​Trzeci udzial, use_count: " << ws_b.use_count() << endl;+        cout << "​Trzeci udzial, use_count: " << ws_b.use_count() << endl;
  
 } }
  
 void auto_ptr_demo() { void auto_ptr_demo() {
- header("​auto_ptr - przy boost maly sens stosowania"​);​ +        ​header("​auto_ptr - przy boost maly sens stosowania"​);​ 
- /* +        /* 
-  * http://​gcc.gnu.org/​onlinedocs/​libstdc++/​libstdc++-html-USERS-4.0/​classstd_1_1auto__ptr.html +         ​* 
-  +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 +         ​* "​auto_ptr does not meet the CopyConstructible and Assignable 
-  * instantiating a Standard Library container with an auto_ptr results in  +         ​* requirements for Standard Library container elements and thus 
-  * undefined behavior."​ +         ​* 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  +         ​* Reasumując - auto_ptr ciekawy nie jest. Potrafi tylko oddawać powiązanie z  
-  * kontenerach nie jest możliwe. +         ​* obiektem, natomiast nie potrafi się nim dzielić. Zastosowanie w  
-  */+         ​* kontenerach nie jest możliwe. 
 +         ​*/
  
- auto_ptr<​Harry>​ a1(new Harry); +        ​auto_ptr<​Harry>​ a1(new Harry); 
- cout << "NEW. " << a1.get() << endl; +        cout << "NEW. " << a1.get() << endl; 
- auto_ptr<​Harry>​ a2(a1); +        auto_ptr<​Harry>​ a2(a1); 
- cout << "1st transfer, source: " << a1.get() << endl; +        cout << "1st transfer, source: " << a1.get() << endl; 
- cout << "1st transfer, dest. : " << a2.get() << endl; +        cout << "1st transfer, dest. : " << a2.get() << endl; 
- auto_ptr<​Harry>​ a3 = a2; +        auto_ptr<​Harry>​ a3 = a2; 
- cout << "2nd transfer, source: " << a2.get() << endl; +        cout << "2nd transfer, source: " << a2.get() << endl; 
- cout << "2nd transfer, dest. : " << a3.get() << endl;+        cout << "2nd transfer, dest. : " << a3.get() << endl;
 } }
  
Linia 566: Linia 609:
  
 int main(int argc, char** argv) { int main(int argc, char** argv) {
- // ========================================================== +        ​// ========================================================== 
- // Zestaw tego, czego robić nie wolno ze scoped_ptr +        // Zestaw tego, czego robić nie wolno ze scoped_ptr 
- play_dirty_harry();​+        play_dirty_harry();​
  
- // shared_ptr +        ​// shared_ptr 
- general_use();​+        general_use();​
  
- // Mniej interesujące +        ​// Mniej interesujące 
- play_nice_harry();​ +        play_nice_harry();​ 
- // Bardziej interesujące +        // Bardziej interesujące 
- play_nice_harry3();​ +        play_nice_harry3();​ 
-  +         
- // scoped_array zamiast scoped_ptr - właściwe delete, konkretnie delete[] +        // scoped_array zamiast scoped_ptr - właściwe delete, konkretnie delete[] 
- play_scoped_array();​+        play_scoped_array();​
  
- // Niewirtualny destruktor. Różnice między zwykłym wskaźnikiem a shared_ptr +        ​// Niewirtualny destruktor. Różnice między zwykłym wskaźnikiem a shared_ptr 
- non_virt_diffs();​+        non_virt_diffs();​
  
- // ========================================================== +        ​// ========================================================== 
- // Kontener STL +        // Kontener STL 
- stl_container();​+        stl_container();​
  
- // ========================================================== +        ​// ========================================================== 
- // Shared vs Weak a cykle+        // Shared vs Weak a cykle
  
- no_cycle();​ +        ​no_cycle();​ 
- shared_cycle();​ +        shared_cycle();​ 
- weak_cycle();​ +        weak_cycle();​ 
- shared_and_weak();​+        shared_and_weak();​
  
- // ========================================================== +        ​// ========================================================== 
- //  GŁÓWNY POWÓD UŻYWANIA SMART_PTRów +        //  GŁÓWNY POWÓD UŻYWANIA SMART_PTRów 
- //    komfort operatora "​new"​ +        //    komfort operatora "​new"​ 
- //    z bezpieczeństwem zmiennych automatycznych +        //    z bezpieczeństwem zmiennych automatycznych 
- // ========================================================== +        // ========================================================== 
- try { +        try { 
- comfort_test();​ +                comfort_test();​ 
- } catch (...) { +        } catch (...) { 
- cout << "​Caught!"​ << endl; +                cout << "​Caught!"​ << endl; 
- }+        }
  
- // ========================================================== +        ​// ========================================================== 
- // Test enable_shared_from_this<>​ +        // Test enable_shared_from_this<>​ 
- boost::​shared_ptr<​WithSharing>​ ws(new WithSharing);​ +        boost::​shared_ptr<​WithSharing>​ ws(new WithSharing);​ 
- with_sharing_test(*ws);​+        with_sharing_test(*ws);​
  
- // ========================================================== +        ​// ========================================================== 
- // std::​auto_ptr +        // std::​auto_ptr 
- auto_ptr_demo();​+        auto_ptr_demo();​
  
- // ========================================================== +        ​// ========================================================== 
- // Intrusive test +        // Intrusive test 
- test_intrusive_ptr();​+        test_intrusive_ptr();​
  
- return 0;+        ​return 0;
 } }
 +
 +
 +
 </​code>​ </​code>​
smart_ptr.txt · ostatnio zmienione: 2008/10/23 11:03 przez rnowak2