C++:智能指针-TR1的shared_ptr和weak_ptr使用介绍

shared_ptr: Based on a reference counter model, with the counter incremented each time a new shared pointer object points to the resource, and decremented when the object's destructor executes; when the counter gets to 0, the resource is released. This pointer is copy constructable and assignable; this makes it usable in STL containers. Moreover, the shared pointer works with polymorphic types and incomplete types. Its major drawback is the impossibility to detect cyclic dependencies, in which case the resources never get released (for example, a tree with nodes having (shared) pointers to children but also to the parent, in which case the parent and the children are referencing each other, in a cycle). To fix this issue, a second smart pointer was created:

weak_ptr: Points to a resource referred by a shared pointer, but does not participate in reference counting. When the counters gets to 0, the resource is released, regardless the number of weak pointers referring it; all these pointers are marked as invalid.

A sharted_ptr object has the ownership of an object if:
 * It was constructed with a pointer to that resource;
 * It was constructed from a shared_ptr object that owns that resource;
 * It was constructed from a weak_ptr object that points to that resource;
Ownership of that resource was assigned to it, either with shared_ptr::operator= or by calling the member function shared_ptr::reset().

Can create a new shared_ptr from:
 * A pointer to any type T (including const T), having the possibility of specifying a deleter for the pointed resource;
 * Another shared_ptr object;
 * A weak_ptr object;
 * An auto_ptr object;

1.get() 返回对象指针;use_count() 返回对象的引用计数

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. class Foo
   5. {
   6. public:
   7.     void print()
   8.     {
   9.         std::cout << " foo::print" << std::endl;
  10.     }
  11. };
  12. 
  13. /* When sp2 is created, sp1 increments the reference counter.
  14.  * When the two shared pointer objects get out of scope, the last
  15.  * one that is destroyed will release the resource.
  16.  *
  17.  * output:
  18.  * foo::print
  19.  * sp1 pointer: 0x90a7008
  20.  * foo::print
  21.  * sp1 pointer: 0x90a7008
  22.  * sp2 pointer: 0x90a7008
  23.  * counter sp1: 2
  24.  * counter sp2: 2
  25.  */
  26. int main()
  27. {
  28.     std::tr1::shared_ptr<Foo> sp1(new Foo);
  29.     sp1->print();
  30.     std::cout << "sp1 pointer: " << sp1.get() << std::endl;
  31. 
  32.     std::tr1::shared_ptr<Foo> sp2(sp1);
  33.     sp2->print();
  34.     std::cout << "sp1 pointer: " << sp1.get() << std::endl;
  35.     std::cout << "sp2 pointer: " << sp2.get() << std::endl;
  36. 
  37.     std::cout << "counter sp1: " << sp1.use_count() << std::endl;
  38.     std::cout << "counter sp2: " << sp2.use_count() << std::endl;
  39. 
  40.     return 0;
  41. }


2.相比较shared_ptr,auto_ptr在赋值与别人后,是放弃对象引用的。

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. class Foo
   5. {
   6. public:
   7.     void print()
   8.     {
   9.         std::cout << " foo::print" << std::endl;
  10.     }
  11. };
  12. 
  13. /* The next sample shows a shared_ptr created from an auto_ptr object. The auto pointer gives up the ownership of the resource,
  14.  * resetting its wrapped pointer to NULL.
  15.  *
  16.  * output:
  17.  * foo::print
  18.  * ap1 pointer: 0x99b8008
  19.  * foo::print
  20.  * ap1 pointer: 0
  21.  * sp1 pointer: 0x99b8008
  22.  */
  23. int main()
  24. {
  25.     std::auto_ptr<Foo> ap1(new Foo);
  26.     ap1->print();
  27.     std::cout << "ap1 pointer: " << ap1.get() << std::endl;
  28. 
  29.     std::tr1::shared_ptr<Foo> sp1(ap1);
  30.     sp1->print();
  31.     std::cout << "ap1 pointer: " << ap1.get() << std::endl;
  32.     std::cout << "sp1 pointer: " << sp1.get() << std::endl;
  33. 
  34.     return 0;
  35. }


3.在shared_ptr构造函数中,行参指定构造对象和析构对象的函数

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. class Foo
   5. {
   6. public:
   7.     void print()
   8.     {
   9.         std::cout << " foo::print" << std::endl;
  10.     }
  11. };
  12. 
  13. class FooHandler
  14. {
  15. public:
  16.     static Foo* alloc()
  17.     {
  18.         Foo* f = new Foo;
  19.         std::cout << " a new foo was created" << std::endl;
  20.         return f;
  21.     }
  22. 
  23.     static void free(Foo* f)
  24.     {
  25.         delete f;
  26.         std::cout << " foo destroyed" << std::endl;
  27.     }
  28. };
  29. 
  30. /*
  31.  * Each time a new object is created or destroyed, a message is printed in the output window (for simplicity, you will ignore the copy
  32.  * construction or assignment). Function FooHandler::free can be provided as a delete to the shared_ptr constructor. As a result,
  33.  * when the resource is deleted a message is printed in the output window (you have to run in debugger to see it).
  34.  *
  35.  * output:
  36.  * a new foo was created
  37.  * foo::print
  38.  * foo destroyed
  39.  */
  40. int main()
  41. {
  42.     std::tr1::shared_ptr<Foo> ptr(FooHandler::alloc(), &FooHandler::free);
  43.     ptr->print();
  44. 
  45.     return 0;
  46. }


4.get() 返回对象指针,使用->调用成员函数

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. class Foo
   5. {
   6. public:
   7.     void print()
   8.     {
   9.         std::cout << " foo::print" << std::endl;
  10.     }
  11. };
  12. 
  13. /*
  14.  * Function get() returns the wrapped pointer to the resource (basically identical to operator-> and available for compatibility
  15.  * with auto_ptr).
  16.  *
  17.  * output:
  18.  * foo::print
  19.  */
  20. int main()
  21. {
  22.     std::tr1::shared_ptr<Foo> sp(new Foo);
  23.     Foo* f = sp.get();
  24.     if (f)
  25.         f->print();
  26. 
  27.     return 0;
  28. }


5.get() 返回对象指针,if判断是否为null

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. /* Class shared_ptr defines a bool operator that allows shared pointers to be used in boolean expressions.
   5.  * With auto_ptr, that is not possible; you have to use function get() to access the internal pointer and check it against NULL.
   6.  */
   7. class PtrUtil
   8. {
   9. public:
  10.     static void is_empty(std::tr1::shared_ptr<std::string> ptr)
  11.     {
  12.         if (ptr)
  13.             std::cout << "not empty" << std::endl;
  14.         else
  15.             std::cout << "is empty" << std::endl;
  16.     }
  17. };
  18. 
  19. /*
  20.  * output:
  21.  * is empty
  22.  * not empty
  23.  */
  24. int main()
  25. {
  26.     std::tr1::shared_ptr<std::string> sp1;
  27.     std::tr1::shared_ptr<std::string> sp2(new std::string("demo"));
  28. 
  29.     PtrUtil::is_empty(sp1);
  30.     PtrUtil::is_empty(sp2);
  31. 
  32.     return 0;
  33. }


6.swap() 交换两个shared_ptr所指向的对象

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. class PtrUtil
   5. {
   6. public:
   7.     static void is_empty(std::tr1::shared_ptr<std::string> ptr)
   8.     {
   9.         if (ptr)
  10.             std::cout << "not empty" << std::endl;
  11.         else
  12.             std::cout << "is empty" << std::endl;
  13.     }
  14. };
  15. 
  16. /* Method swap() : exchange the content of the shared pointers.
  17.  *
  18.  * output:
  19.  * is empty
  20.  * not empty
  21.  * not empty
  22.  * is empty
  23.  */
  24. int main()
  25. {
  26.     std::tr1::shared_ptr<std::string> sp1;
  27.     std::tr1::shared_ptr<std::string> sp2(new std::string("demo"));
  28. 
  29.     PtrUtil::is_empty(sp1);
  30.     PtrUtil::is_empty(sp2);
  31. 
  32.     sp1.swap(sp2);
  33. 
  34.     PtrUtil::is_empty(sp1);
  35.     PtrUtil::is_empty(sp2);
  36. 
  37.     return 0;
  38. }


7.使用等号赋值

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. /* operator= is overloaded so that a shared pointer can be assigned from another shared_ptr or auto_ptr.
   5.  *
   6.  * output:
   7.  * sp1 = 1
   8.  * sp2 = 2
   9.  * sp1 = 2
  10.  */
  11. int main()
  12. {
  13.     std::tr1::shared_ptr<int> sp1(new int(1));
  14.     std::cout << "sp1 = " << *sp1 << std::endl;
  15. 
  16.     std::tr1::shared_ptr<int> sp2(new int(2));
  17.     std::cout << "sp2 = " << *sp2 << std::endl;
  18. 
  19.     sp1 = sp2;
  20.     std::cout << "sp1 = " << *sp1 << std::endl;
  21. 
  22.     return 0;
  23. }


8.unique() 判断当前对象的引用计数==1?

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. /* Method use_count() returns the number of references to the shared resource (pointed by the current shared pointer object).
   5.  * Method unique() indicates whether another shared pointed shares the ownership of the same resource or not
   6.  * (basically, it's identical to 1 == use_count()).
   7.  *
   8.  * output:
   9.  * unique : true
  10.  * counter : 1
  11.  * unique : false
  12.  * counter : 2
  13.  */
  14. int main()
  15. {
  16.     std::tr1::shared_ptr<std::string> sp1(new std::string("marius bancila"));
  17.     std::cout << "unique : " << std::boolalpha << sp1.unique() << std::endl;
  18.     std::cout << "counter : " << sp1.use_count() << std::endl;
  19.     std::tr1::shared_ptr<std::string> sp2(sp1);
  20.     std::cout << "unique : " << std::boolalpha << sp1.unique() << std::endl;
  21.     std::cout << "counter : " << sp1.use_count() << std::endl;
  22. 
  23.     return 0;
  24. }


9.reset() 清空当前shared指针,并将所有基于该指针创建的shared指针的引用计数减1

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. class Foo
   5. {
   6. public:
   7.     void print()
   8.     {
   9.         std::cout << " foo::print" << std::endl;
  10.     }
  11. };
  12. 
  13. /*Function reset() decrements the shared reference counter. It then transforms the shared pointer to an empty shared_ptr.
  14.  *
  15.  * output:
  16.  * counter sp1: 1
  17.  * counter sp1: 3
  18.  * counter sp2: 3
  19.  * counter sp3: 3
  20.  * counter sp1: 0
  21.  * counter sp2: 2
  22.  * counter sp3: 2
  23.  * counter sp1: 0
  24.  * counter sp2: 0
  25.  * counter sp3: 1
  26.  */
  27. int main()
  28. {
  29.     // a shared_ptr owns the resouce, counter is 1
  30.     std::tr1::shared_ptr<Foo> sp1(new Foo);
  31.     std::cout << "counter sp1: " << sp1.use_count() << std::endl;
  32. 
  33.     std::tr1::shared_ptr<Foo> sp2(sp1);
  34.     std::tr1::shared_ptr<Foo> sp3(sp2);
  35.     std::cout << "counter sp1: " << sp1.use_count() << std::endl;
  36.     std::cout << "counter sp2: " << sp2.use_count() << std::endl;
  37.     std::cout << "counter sp3: " << sp3.use_count() << std::endl;
  38. 
  39.     // first shared_ptr is reset, the counter decremented and the object becomes empty
  40.     sp1.reset();
  41.     std::cout << "counter sp1: " << sp1.use_count() << std::endl;
  42.     std::cout << "counter sp2: " << sp2.use_count() << std::endl;
  43.     std::cout << "counter sp3: " << sp3.use_count() << std::endl;
  44. 
  45.     sp2.reset();
  46.     std::cout << "counter sp1: " << sp1.use_count() << std::endl;
  47.     std::cout << "counter sp2: " << sp2.use_count() << std::endl;
  48.     std::cout << "counter sp3: " << sp3.use_count() << std::endl;
  49. 
  50.     return 0;
  51. }


10.对引用计数的理解,在容器中使用shared_ptr

   1. #include <iostream>
   2. #include <tr1/memory>
   3. #include <vector>
   4. #include <algorithm>
   5. 
   6. /* The following sample shows a vector of shared_ptr to int; a transformation is applied on the elements of the vector,
   7.  * doubling the value of the pointed objects.
   8.  *
   9.  * The program shows the reference counter to show that calling function double_it() does not affect it, even though this function
  10.  * returns a shared_ptr by value.
  11.  */
  12. std::tr1::shared_ptr<int> double_it(const std::tr1::shared_ptr<int>& sp)
  13. {
  14.     *sp *= 2;
  15.     return sp;
  16. }
  17. 
  18. /*
  19.  * output:
  20.  * initially
  21.  * 1 (counter = 1)
  22.  * 2 (counter = 1)
  23.  * 3 (counter = 1)
  24.  * after transformation
  25.  * 2 (counter = 1)
  26.  * 4 (counter = 1)
  27.  * 6 (counter = 1)
  28.  */
  29. int main()
  30. {
  31.     std::vector<std::tr1::shared_ptr<int> > numbers;
  32. 
  33.     numbers.push_back(std::tr1::shared_ptr<int>(new int(1)));
  34.     numbers.push_back(std::tr1::shared_ptr<int>(new int(2)));
  35.     numbers.push_back(std::tr1::shared_ptr<int>(new int(3)));
  36. 
  37.     std::cout << "initially" << std::endl;
  38.     for (std::vector<std::tr1::shared_ptr<int> >::const_iterator it =
  39.             numbers.begin(); it != numbers.end(); ++it)
  40.         std::cout << **it << " (counter = " << (*it).use_count() << ")"
  41.                 << std::endl;
  42.     std::transform(numbers.begin(), numbers.end(), numbers.begin(), double_it);
  43.     std::cout << "after transformation" << std::endl;
  44.     for (std::vector<std::tr1::shared_ptr<int> >::const_iterator it =
  45.             numbers.begin(); it != numbers.end(); ++it)
  46.         std::cout << **it << " (counter = " << (*it).use_count() << ")"
  47.                 << std::endl;
  48. 
  49.     return 0;
  50. }


11.多态情况下的shared指针使用(声明基类句柄,创建子类对象)

   1. #include <iostream>
   2. #include <tr1/memory>
   3. #include <vector>
   4. 
   5. /*shared_ptr can work with class hierarchies, so that shared<D> is convertible to shared<B>, where D is a class (or struct) derived
   6.  * from B. The following class hierarchy is used to demonstrate the concept.
   7.  */
   8. class Item
   9. {
  10.     std::string title_;
  11. public:
  12.     Item(const std::string& title) :
  13.         title_(title)
  14.     {
  15.     }
  16.     virtual ~Item()
  17.     {
  18.     }
  19. 
  20.     virtual std::string Description() const = 0;
  21.     std::string Title() const
  22.     {
  23.         return title_;
  24.     }
  25. };
  26. 
  27. class Book: public Item
  28. {
  29.     int pages_;
  30. public:
  31.     Book(const std::string& title, int pages) :
  32.         Item(title), pages_(pages)
  33.     {
  34.     }
  35. 
  36.     virtual std::string Description() const
  37.     {
  38.         return "Book: " + Title();
  39.     }
  40.     int Pages() const
  41.     {
  42.         return pages_;
  43.     }
  44. };
  45. 
  46. class DVD: public Item
  47. {
  48.     int tracks_;
  49. public:
  50.     DVD(const std::string& title, int tracks) :
  51.         Item(title), tracks_(tracks)
  52.     {
  53.     }
  54. 
  55.     virtual std::string Description() const
  56.     {
  57.         return "DVD: " + Title();
  58.     }
  59.     int Tracks() const
  60.     {
  61.         return tracks_;
  62.     }
  63. };
  64. 
  65. /*
  66.  * output:
  67.  * Book: Effective STL
  68.  * DVD: Left of the Middle
  69.  */
  70. int main()
  71. {
  72.     std::vector<std::tr1::shared_ptr<Item> > items;
  73.     items.push_back(std::tr1::shared_ptr<Book>(new Book("Effective STL", 400)));
  74.     items.push_back(std::tr1::shared_ptr<DVD>(new DVD("Left of the Middle", 14)));
  75. 
  76.     for (std::vector<std::tr1::shared_ptr<Item> >::const_iterator it =
  77.             items.begin(); it != items.end(); ++it)
  78.         std::cout << (*it)->Description() << std::endl;
  79. 
  80.     return 0;
  81. }


12.dynamic_cast,使用dynamic_pointer_cast将基类向下转型为子类

   1. #include <iostream>
   2. #include <tr1/memory>
   3. #include <vector>
   4. 
   5. /*shared_ptr can work with class hierarchies, so that shared<D> is convertible to shared<B>, where D is a class (or struct) derived
   6.  * from B. The following class hierarchy is used to demonstrate the concept.
   7.  */
   8. class Item
   9. {
  10.     std::string title_;
  11. public:
  12.     Item(const std::string& title) :
  13.         title_(title)
  14.     {
  15.     }
  16.     virtual ~Item()
  17.     {
  18.     }
  19. 
  20.     virtual std::string Description() const = 0;
  21.     std::string Title() const
  22.     {
  23.         return title_;
  24.     }
  25. };
  26. 
  27. class Book: public Item
  28. {
  29.     int pages_;
  30. public:
  31.     Book(const std::string& title, int pages) :
  32.         Item(title), pages_(pages)
  33.     {
  34.     }
  35. 
  36.     virtual std::string Description() const
  37.     {
  38.         return "Book: " + Title();
  39.     }
  40.     int Pages() const
  41.     {
  42.         return pages_;
  43.     }
  44. };
  45. 
  46. class DVD: public Item
  47. {
  48.     int tracks_;
  49. public:
  50.     DVD(const std::string& title, int tracks) :
  51.         Item(title), tracks_(tracks)
  52.     {
  53.     }
  54. 
  55.     virtual std::string Description() const
  56.     {
  57.         return "DVD: " + Title();
  58.     }
  59.     int Tracks() const
  60.     {
  61.         return tracks_;
  62.     }
  63. };
  64. 
  65. /* To convert back, from shared_ptr<B> to shared_ptr<D>, where D is a class (or structure) derived from B,
  66.  * you can use the cast function std::tr1::dynamic_pointer_cast.
  67.  *
  68.  * output:
  69.  * spi counter: 1
  70.  * Left of the Middle, 14 tracks
  71.  * spi counter: 2
  72.  * spb counter: 0
  73.  * spd counter: 2
  74.  */
  75. int main()
  76. {
  77.     std::tr1::shared_ptr<Item> spi(new DVD("Left of the Middle", 14));
  78.     std::cout << "spi counter: " << spi.use_count() << std::endl;
  79.     std::tr1::shared_ptr<Book> spb = std::tr1::dynamic_pointer_cast<Book>(spi);
  80.     if (spb)
  81.         std::cout << spb->Title() << ", " << spb->Pages() << " pages" << std::endl;
  82. 
  83.     std::tr1::shared_ptr<DVD> spd = std::tr1::dynamic_pointer_cast<DVD>(spi);
  84.     if (spd)
  85.         std::cout << spd->Title() << ", " << spd->Tracks() << " tracks"    << std::endl;
  86. 
  87.     std::cout << "spi counter: " << spi.use_count() << std::endl;
  88.     std::cout << "spb counter: " << spb.use_count() << std::endl;
  89.     std::cout << "spd counter: " << spd.use_count() << std::endl;
  90. 
  91.     return 0;
  92. }


13.static cast,使用static_pointer_cast将void转型为char,观察引用计数的变化

   1. #include <iostream>
   2. #include <tr1/memory>
   3. #include <vector>
   4. 
   5. /* A second cast function is std::tr1::static_pointer_cast. It returns an empty shared_ptr if the original object is empty,
   6.  * or a shared_ptr<T> object that owns the resource that is owned by the original object. The expression static_cast<T*>(r.get())
   7.  * must be valid.
   8.  *
   9.  * In the next sample, a vector holds shared_ptr to void. The first element is statically cast to shared_ptr<char>.
  10.  * The cast is valid as long as the source is not empty, regardless of whether the types are compatible or not.
  11.  *
  12.  * output:
  13.  * after creating the shared pointer
  14.  * -1    sp1 counter: 1
  15.  * after adding to the vector
  16.  * -2    sp1 counter: 2
  17.  * A
  18.  * after casting
  19.  * -3    sp1 counter: 3
  20.  * -4    spc counter: 3
  21.  */
  22. int main()
  23. {
  24.     std::vector<std::tr1::shared_ptr<void> > items;
  25.     std::tr1::shared_ptr<char> sp1(new char('A'));
  26.     std::tr1::shared_ptr<short> sp2(new short(66));
  27.     std::cout << "after creating the shared pointer" << std::endl;
  28.     std::cout << "-1    sp1 counter: " << sp1.use_count() << std::endl;
  29.     items.push_back(sp1);
  30.     items.push_back(sp2);
  31.     std::cout << "after adding to the vector" << std::endl;
  32.     std::cout << "-2    sp1 counter: " << sp1.use_count() << std::endl;
  33.     std::tr1::shared_ptr<char> spc = std::tr1::static_pointer_cast<char>(*(items.begin()));
  34.     if (spc)
  35.         std::cout << *spc << std::endl;
  36.     std::cout << "after casting" << std::endl;
  37.     std::cout << "-3    sp1 counter: " << sp1.use_count() << std::endl;
  38.     std::cout << "-4    spc counter: " << spc.use_count() << std::endl;
  39. 
  40.     return 0;
  41. }


14.const cast,如果声明std::tr1::shared_ptr<const int> csp,可以声明std::tr1::shared_ptr<int> sp = std::tr1::const_pointer_cast<int>(csp);

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. /* To modify the value of the pointer object the const specifier must be removed. This is shown below.
   5.  *
   6.  * output:
   7.  * csp counter: 1
   8.  * 15
   9.  * 15
  10.  * csp counter: 2
  11.  * sp counter: 2
  12.  */
  13. int main()
  14. {
  15.     std::tr1::shared_ptr<const int> csp(new int(5));
  16.     std::cout << "csp counter: " << csp.use_count() << std::endl;
  17. 
  18.     std::tr1::shared_ptr<int> sp = std::tr1::const_pointer_cast<int>(csp);
  19.     *sp += 10;
  20. 
  21.     std::cout << *csp << std::endl;
  22.     std::cout << *sp << std::endl;
  23. 
  24.     std::cout << "csp counter: " << csp.use_count() << std::endl;
  25.     std::cout << "sp counter: " << sp.use_count() << std::endl;
  26. 
  27.     return 0;
  28. }


15.weak_ptr的lock() 类似于shared_ptr的get()

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. /* The major weakness of shared_ptr is that it cannot detect cyclic dependencies. In this case, the reference counter is incremented
   5.  * more than it should actually be, so that the resources are no longer released when the shared pointer objects go out of scope.
   6.  * To fix this problem, a second smart pointer was created, weak_ptr, that points to a resource owned by a shared_ptr but does not
   7.  * affect the reference counter; it is a "weak reference." When the last shared_ptr that owns the resource referred by a weak_ptr,
   8.  * the resource is released and the weak pointer is marked as invalid. To check whether a weak_ptr is valid or not, you can use
   9.  * function expired() that returns true if the pointer was marked as invalid.
  10.  */
  11. 
  12. /* Even though function get() (that provides direct access to the wrapped pointer) is available, it's not recommended to use it even
  13.  * in single-threaded applications. The safe alternative is function lock() that returns a shread_ptr sharing the resource pointed by
  14.  * the weak pointer.*/
  15. void show(const std::tr1::weak_ptr<int>& wp)
  16. {
  17.     std::tr1::shared_ptr<int> sp = wp.lock();
  18.     std::cout << *sp << std::endl;
  19. }
  20. 
  21. /*
  22.  * output:
  23.  * 44
  24.  * expired : true
  25.  */
  26. int main()
  27. {
  28.     std::tr1::weak_ptr<int> wp;
  29.     {
  30.         std::tr1::shared_ptr<int> sp(new int(44));
  31.         wp = sp;
  32.         show(wp);
  33.     }
  34.     std::cout << "expired : " << std::boolalpha << wp.expired() << std::endl;
  35. 
  36.     return 0;
  37. }


16.一个使用shared_ptr和weak_ptr的二叉树数据结构示例

   1. #include <iostream>
   2. #include <tr1/memory>
   3. 
   4. /* The following sample shows such a tree, but uses a weak_ptr to solve the cyclic dependency.*/
   5. class Node
   6. {
   7.     std::string value_;
   8.     std::tr1::shared_ptr<Node> left_;
   9.     std::tr1::shared_ptr<Node> right_;
  10.     std::tr1::weak_ptr<Node> parent_;
  11. 
  12. public:
  13.     Node(const std::string value) :
  14.         value_(value)
  15.     {
  16.     }
  17. 
  18.     std::string Value() const
  19.     {
  20.         return value_;
  21.     }
  22.     std::tr1::shared_ptr<Node> Left() const
  23.     {
  24.         return left_;
  25.     }
  26.     std::tr1::shared_ptr<Node> Right() const
  27.     {
  28.         return right_;
  29.     }
  30.     std::tr1::weak_ptr<Node> Parent() const
  31.     {
  32.         return parent_;
  33.     }
  34. 
  35.     void SetParent(std::tr1::shared_ptr<Node> node)
  36.     {
  37.         parent_.reset();
  38.         parent_ = node;
  39.     }
  40. 
  41.     void SetLeft(std::tr1::shared_ptr<Node> node)
  42.     {
  43.         left_.reset();
  44.         left_ = node;
  45.     }
  46. 
  47.     void SetRight(std::tr1::shared_ptr<Node> node)
  48.     {
  49.         right_.reset();
  50.         right_ = node;
  51.     }
  52. };
  53. 
  54. std::string path(const std::tr1::shared_ptr<Node>& item)
  55. {
  56.     std::tr1::weak_ptr<Node> wparent = item->Parent();
  57.     std::tr1::shared_ptr<Node> sparent = wparent.lock();
  58. 
  59.     if (sparent)
  60.     {
  61.         return path(sparent) + "//" + item->Value();
  62.     }
  63. 
  64.     return item->Value();
  65. }
  66. 
  67. /*
  68.  * output:
  69.  * C:/dir1/dir11
  70.  */
  71. int main()
  72. {
  73.     std::tr1::shared_ptr<Node> root(new Node("C:"));
  74. 
  75.     std::tr1::shared_ptr<Node> child1(new Node("dir1"));
  76.     std::tr1::shared_ptr<Node> child2(new Node("dir2"));
  77. 
  78.     root->SetLeft(child1);
  79.     child1->SetParent(root);
  80. 
  81.     root->SetRight(child2);
  82.     child2->SetParent(root);
  83. 
  84.     std::tr1::shared_ptr<Node> child11(new Node("dir11"));
  85. 
  86.     child1->SetLeft(child11);
  87.     child11->SetParent(child1);
  88. 
  89.     std::cout << "path: " << path(child11) << std::endl;
  90. 
  91.     return 0;
  92. }

本文出自 “子 孑” 博客,请务必保留此出处http://zhangjunhd.blog.51cto.com/113473/148628

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值