shared_ptr & weak_ptr

shared_ptr

<1> 类模板说明

  1 namespace boost
  2 {
  3     class bad_weak_ptr: public std::exception;
  4     template<class T> class weak_ptr;
  5     template<class T> class shared_ptr
  6     {
  7     public:
  8         typedef T element_type;
  9 1.1 构造与析构
 10 /* 1.1.1 默认构造 */
 11         说明:构造一个空的shared_ptr
 12         结果:use_count() == 0 && get() == 0
 13         shared_ptr(); // never throws
 14         shared_ptr(std::nullptr_t); // never throws
 15 /* 1.1.2 指针构造 */
 16         说明:Y必须是一个完整的类型,Y*应该可以转换为T*。p必须是通过new分配的指针或者0。
 17         结果:use_count() == 1 && get() == p
 18         template<class Y> explicit shared_ptr(Y * p);
 19 /* 1.1.3 带有析构器的构造 */
 20         说明:构造一个包含指针p和析构器d的shared_ptr。
 21         结果:use_count() == 1 && get() == p
 22         template<class Y, class D> shared_ptr(Y * p, D d);
 23         template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
 24         template<class D> shared_ptr(std::nullptr_t p, D d);
 25               template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
 26 /* 1.1.4 复制和转换构造 */
 27         说明:Y*应该可以转换为T*。如果r为空,则构造一个空的shared_ptr;否则构造一个与r同样拥有权的shared_ptr
 28         结果:use_count() == r.use_count() && get() == r.get()
 29               shared_ptr(shared_ptr const & r); // never throws
 30               template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
 31 /* 1.1.5 移动构造 */
 32         说明:Y*应该可以转换为T* 33         结果:*this包含r中的旧值,r == 0 && r.get() == 0
 34               shared_ptr(shared_ptr && r); // never throws
 35               template<class Y> shared_ptr(shared_ptr<Y> && r); // never throws
 36 /* 1.1.6 别名构造 */
 37         说明:构造一个shared_ptr,与r同样的拥有权,并且包含p
 38         结果:use_count() == r.use_count() && get() == p
 39               template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p); // never throws
 40 /* 1.1.7 weak_ptr构造 */
 41         说明:Y*应该可以转换为T*。构造一个shared_ptr,与r同样的拥有权,并且包含一个r中指针的副本
 42         结果:use_count() == r.use_count()
 43               template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
 44 /* 1.1.8 auto_ptr构造 */
 45         说明:Y*应该可以转换为T* 46         结果:use_count() == 1
 47               template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
 48               template<class Y> shared_ptr(std::auto_ptr<Y> && r);
 49 /* 1.1.9 unique_ptr构造 */
 50         说明:Y*应该可以转换为T*。等价于shared_ptr(r.release(), r.get_deleter())
 51         结果:use_count() == 1
 52               template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
 53 /* 1.1.10 析构函数 */
 54         说明:
 55             如果*this为空,或者拥有其他shared_ptr实例的控制权(use_count() > 1),那么什么都不做;
 56             如果*this拥有一个指针p和一个析构器d,那么调用d(p);
 57             如果*this拥有一个指针p,那么调用delete p。
 58         ~shared_ptr(); // never throws
 59 1.2 赋值操作符
 60         说明:等价于shared_ptr(r).swap(*this),返回*this 61               shared_ptr & operator=(shared_ptr const & r); // never throws
 62               template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
 63         template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
 64 
 65         说明:等价于shared_ptr(std::move(r)).swap(*this),返回*this 66               shared_ptr & operator=(shared_ptr const && r); // never throws
 67               template<class Y> shared_ptr & operator=(shared_ptr<Y> const && r); // never throws
 68               template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
 69               template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
 70         说明:等价于shared_ptr().swap(*this),返回*this 71               shared_ptr & operator=(std::nullptr_t); // never throws
 72 1.3 重置操作
 73         说明:等价于shared_ptr().swap(*this)。
 74               void reset(); // never throws
 75         说明:等价于shared_ptr(p).swap(*this)。
 76               template<class Y> void reset(Y * p);
 77         说明:等价于shared_ptr(p, d).swap(*this)。
 78               template<class Y, class D> void reset(Y * p, D d);
 79         说明:等价于shared_ptr(p, d, a).swap(*this)。
 80               template<class Y, class D, class A> void reset(Y * p, D d, A a);
 81         说明:等价于shared_ptr(r, p).swap(*this)。
 82               template<class Y> void reset(shared_ptr<Y> const & r, element_type * p); // never throws
 83 1.4 间接操作
 84               T & operator*() const; // never throws; only valid when T is not an array type
 85               T * operator->() const; // never throws; only valid when T is not an array type
 86 
 87               element_type & operator[](std::ptrdiff_t i) const; // never throws; only valid when T is an array type
 88 1.5 逻辑运算
 89         说明:如果a.get() == b.get(),则返回true。
 90         template<class T, class U>
 91             bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
 92         说明:如果a.get() != b.get(),则返回true。
 93           template<class T, class U>
 94             bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
 95 
 96           template<class T, class U>
 97             bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
 98         说明:如果p.get() == 0,则返回true。
 99           template<class T>
100             bool operator==(shared_ptr<T> const & p, std::nullptr_t); // never throws
101           template<class T>
102             bool operator==(std::nullptr_t, shared_ptr<T> const & p); // never throws
103         说明:如果p.get() != 0,则返回true。
104           template<class T>
105             bool operator!=(shared_ptr<T> const & p, std::nullptr_t); // never throws
106           template<class T>
107             bool operator!=(std::nullptr_t, shared_ptr<T> const & p); // never throws
108 1.6 其他操作
109         说明:返回原始指针。
110             element_type * get() const; // never throws
111         说明:如果use_count() == 1,则返回true,效率比use_count()高。
112             bool unique() const; // never throws
113         说明:返回shared_ptr的引用计数。
114             long use_count() const; // never throws
115             explicit operator bool() const; // never throws
116         说明:交换两个智能指针的内容。
117             void swap(shared_ptr & b); // never throws
118 
119             template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const; // never throws
120             template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const; // never throws
121       };
122 
123     说明:等价于a.swap(b)。
124       template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
125     说明:返回p.get()。
126       template<class T> typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p); // never throws
127     说明:几种转换操作。
128       template<class T, class U>
129         shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
130       template<class T, class U>
131         shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
132       template<class T, class U>
133         shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws
134       template<class T, class U>
135         shared_ptr<T> reinterpet_pointer_cast(shared_ptr<U> const & r); // never throws
136     说明:执行os << p.get(),返回os。
137       template<class E, class T, class Y>
138         std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
139     说明:返回者p对应的析构器d或者0。
140       template<class D, class T>
141       D * get_deleter(shared_ptr<T> const & p);
142 }
View Code

<2> 示例用法

示例 [1]:(基本用法)

 1 // shared_ptr1.cc
 2 #include <vector>
 3 #include <set>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include <boost/shared_ptr.hpp>
 7 
 8 //  The application will produce a series of
 9 //  objects of type Foo which later must be
10 //  accessed both by occurrence (std::vector)
11 //  and by ordering relationship (std::set).
12 
13 struct Foo
14 {
15   Foo( int _x ) : x(_x) {}
16   ~Foo() { std::cout << "Destructing a Foo with x=" << x << "\n"; }
17   int x;
18   /* ... */
19 };
20 
21 typedef boost::shared_ptr<Foo> FooPtr;
22 
23 struct FooPtrOps
24 {
25   bool operator()( const FooPtr & a, const FooPtr & b )
26     { return a->x > b->x; }
27   void operator()( const FooPtr & a )
28     { std::cout << a->x << "\n"; }
29 };
30 
31 int main()
32 {
33   std::vector<FooPtr>         foo_vector;
34   std::set<FooPtr,FooPtrOps>  foo_set; // NOT multiset!
35 
36   FooPtr foo_ptr( new Foo( 2 ) );
37   foo_vector.push_back( foo_ptr );
38   foo_set.insert( foo_ptr );
39 
40   foo_ptr.reset( new Foo( 1 ) );
41   foo_vector.push_back( foo_ptr );
42   foo_set.insert( foo_ptr );
43 
44   foo_ptr.reset( new Foo( 3 ) );
45   foo_vector.push_back( foo_ptr );
46   foo_set.insert( foo_ptr );
47 
48   foo_ptr.reset ( new Foo( 2 ) );
49   foo_vector.push_back( foo_ptr );
50   foo_set.insert( foo_ptr );
51 
52   std::cout << "foo_vector:\n";
53   std::for_each( foo_vector.begin(), foo_vector.end(), FooPtrOps() );
54 
55   std::cout << "\nfoo_set:\n";
56   std::for_each( foo_set.begin(), foo_set.end(), FooPtrOps() );
57   std::cout << "\n" << "the program is done..." << "\n\n";
58 }
59 
60 // output
61 foo_vector:
62 2
63 1
64 3
65 2
66 
67 foo_set:
68 3
69 2
70 1
71 
72 the program is done...
73 
74 Destructing a Foo with x=2
75 Destructing a Foo with x=1
76 Destructing a Foo with x=3
77 Destructing a Foo with x=2
View Code

示例 [2]:(惯用法)使用shared_ptr来隐藏不完整类型的实现细节。

 1 // shared_ptr2.hpp
 2 #include <boost/shared_ptr.hpp>
 3 
 4 //  This example demonstrates the handle/body idiom (also called pimpl and
 5 //  several other names).  It separates the interface (in this header file)
 6 //  from the implementation (in shared_ptr_example2.cpp).
 7 
 8 //  Note that even though example::implementation is an incomplete type in
 9 //  some translation units using this header, shared_ptr< implementation >
10 //  is still valid because the type is complete where it counts - in the
11 //  shared_ptr_example2.cpp translation unit where functions requiring a
12 //  complete type are actually instantiated.
13 
14 class example
15 {
16 public:
17   example();
18   void do_something();
19 private:
20   class implementation;
21   boost::shared_ptr< implementation > _imp; // hide implementation details
22 };
23 
24 // shared_ptr2.cc
25 #include "shared_ptr2.hpp"
26 #include <iostream>
27 
28 class example::implementation
29 {
30  public:
31   ~implementation() { std::cout << "destroying implementation\n"; }
32 };
33 
34 example::example() : _imp( new implementation ) {}
35 
36 void example::do_something()
37   { std::cout << "use_count() is " << _imp.use_count() << "\n"; }
38 
39 // shared_ptr2_test.cc
40 #include "shared_ptr2.hpp"
41 
42 int main()
43 {
44   example a;
45   a.do_something();
46   example b(a);
47   b.do_something();
48   example c;
49   c = a;
50   c.do_something();
51   return 0;
52 }
53 
54 // output
55 use_count() is 1
56 use_count() is 2
57 destroying implementation
58 use_count() is 3
59 destroying implementation
View Code

示例 [3]:(线程安全性)一个shared_ptr实例可以同时被多个线程<read>(使用const操作访问);不同shared_ptr实例可以同时被多个线程<write>(使用mutable操作访问,例如operator=、reset);如果多个线程需要同时写同一个shared_ptr实例,则需要加锁保护。

 1 shared_ptr<int> p(new int(42));
 2 
 3 //--- Example 1 ---
 4 // thread A
 5 shared_ptr<int> p2(p); // reads p
 6 // thread B
 7 shared_ptr<int> p3(p); // OK, multiple reads are safe
 8 
 9 //--- Example 2 ---
10 // thread A
11 p.reset(new int(1912)); // writes p
12 // thread B
13 p2.reset(); // OK, writes p2
14 
15 //--- Example 3 ---
16 // thread A
17 p = p3; // reads p3, writes p
18 // thread B
19 p3.reset(); // writes p3; undefined, simultaneous read/write
20 
21 //--- Example 4 ---
22 // thread A
23 p3 = p2; // reads p2, writes p3
24 // thread B
25 // p2 goes out of scope: undefined, the destructor is considered a "write access"
26 
27 //--- Example 5 ---
28 // thread A
29 p3.reset(new int(1));
30 // thread B
31 p3.reset(new int(2)); // undefined, multiple writes
View Code

 

weak_ptr

<1> 类模板说明

 1 namespace boost 
 2 {
 3 template<class T> class weak_ptr 
 4 {
 5 public:
 6         typedef T element_type;
 7     说明:构造一个空的weak_ptr,使得use_count() == 0
 8         weak_ptr();
 9     说明:use_count() == r.use_count()
10           template<class Y> weak_ptr(shared_ptr<Y> const & r);
11           weak_ptr(weak_ptr const & r);
12           template<class Y> weak_ptr(weak_ptr<Y> const & r);
13 
14           ~weak_ptr();
15     说明:等价于weak_ptr(r).swap(*this)。
16           weak_ptr & operator=(weak_ptr const & r);
17           template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
18           template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
19     说明:如果*this为空,返回0;否则返回shared_ptr对象中的引用计数。
20           long use_count() const;
21     说明:如果use_count() == 0,返回true。
22           bool expired() const;
23     说明:返回expired()? shared_ptr<T>(): shared_ptr<T>(*this)。
24           shared_ptr<T> lock() const;
25     说明:等价于weak_ptr().swap(*this)。
26           void reset();
27           void swap(weak_ptr<T> & b);
28       };
29 
30       template<class T, class U>
31         bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);
32 
33       template<class T>
34         void swap(weak_ptr<T> & a, weak_ptr<T> & b);
35 }
36     
View Code

 

总结

<1> 关于shared_ptr:

shared_ptr & weak_ptr_第1张图片

shared_ptr类模板用于管理一个动态分配对象的指针(典型地,通过C++中的new表达式)。当所指对象的引用计数为0时,自动调用所指对象的析构函数。在调用析构函数时,是根据构造shared_ptr时传入的指针类型,而非模板参数,如:

shared_ptr<void> p(new int(5));  析构时调用int*类型的析构函数,而非void*类型。

从boost 1.53开始,shared_ptr可以被用来管理动态分配的数组的指针,传入模板参数是可以指定数组的大小,也可以不指定,没什么太大的区别,如下:

shared_ptr<double[1024]> p1(new double[1024]);

shared_ptr<double []> p2(new double[1024]);

 

由于使用了引用计数,那么可能会造成循环引用的问题。如下为示例程序:

 1 // shared_ptr3_cycles.cc
 2 #include <iostream>
 3 #include <memory>
 4 #include <string>
 5 #include <vector>
 6 #include <algorithm>
 7 
 8 using namespace std;
 9 
10 class Controller
11 {
12 public:
13     explicit Controller(int i) : num(i) ,status("On")
14     {
15         cout << "Creating Controller" << num << endl;
16     }
17 
18     ~Controller()
19     {
20         cout << "Destroying Controller" << num << endl;
21     }
22 
23     // Demonstrates how to test whether the pointed-to memory still exists or not.
24     void checkStatuses() const
25     {
26         for_each
27         (others.begin(), others.end(),
28                  [](weak_ptr<Controller> wp)
29                     {
30                         try
31                         {
32                             auto p = wp.lock();
33                             cout << "status of " << p->num << " = " << p->status << endl;
34                         }
35                         catch (bad_weak_ptr b)
36                         {
37                             cout << "null object" << endl;
38                         }
39                     }
40         );
41     }
42 
43     int num;
44     string status;
45     vector<shared_ptr<Controller> > others;
46     //vector<weak_ptr<Controller> > others;     // 使用weak_ptr避免循环引用
47                                                 // Controller 对象表示设备控制器
48                                                 // 由于每个控制器必须能够在任何时间查询其他控制器的状态,因此包含 vector<weak_ptr<Controller> >
49 };
50 
51 void RunTest()
52 {
53     vector<shared_ptr<Controller> > v;
54 
55     v.push_back(shared_ptr<Controller>(new Controller(1)));
56     v.push_back(shared_ptr<Controller>(new Controller(2)));
57     v.push_back(shared_ptr<Controller>(new Controller(3)));
58 
59     // Each controller depends on all others not being deleted.
60     // Give each controller a pointer to all the others.
61     for (int i = 0 ; i < v.size(); ++i)
62     {
63         for_each
64         (v.begin(), v.end(),
65             [v,i](shared_ptr<Controller> p)
66             {
67                 if(p->num != i)
68                 {
69                     v[i]->others.push_back(shared_ptr<Controller>(p));
70                     // v[i]->others.push_back(weak_ptr<Controller>(p));
71                     cout << "push_back to v[" << i << "]: " << p->num << endl;
72                 }
73             }
74         );
75     }
76 
77     for_each
78     (v.begin(), v.end(),
79         [](shared_ptr<Controller>& p)
80         {
81             cout << "use_count = " << p.use_count() << endl;
82             p->checkStatuses();
83         }
84     );
85 }
86 
87 int main()
88 {
89     RunTest();
90     return 0;
91 }
View Code

上述程序运行结果如下:

 1 // output
 2 Creating Controller1
 3 Creating Controller2
 4 Creating Controller3
 5 push_back to v[0]: 1
 6 push_back to v[0]: 2
 7 push_back to v[0]: 3
 8 push_back to v[1]: 2
 9 push_back to v[1]: 3
10 push_back to v[2]: 1
11 push_back to v[2]: 3
12 use_count = 3
13 status of 1 = On
14 status of 2 = On
15 status of 3 = On
16 use_count = 3
17 status of 2 = On
18 status of 3 = On
19 use_count = 4
20 status of 1 = On
21 status of 3 = On

可以发现,上述程序由于出现了循环引用问题,导致析构函数没有调用,如果程序中使用vector<weak_ptr<Controller> > others记录其他控制器的状态,由于不涉及引用计数的增加,因此use_count函数永远返回1,这样就打破了循环引用,只需修改上述程序中注释掉的两行即可,修改后运行结果如下:

 1 Creating Controller3
 2 push_back to v[0]: 1
 3 push_back to v[0]: 2
 4 push_back to v[0]: 3
 5 push_back to v[1]: 2
 6 push_back to v[1]: 3
 7 push_back to v[2]: 1
 8 push_back to v[2]: 3
 9 use_count = 1
10 status of 1 = On
11 status of 2 = On
12 status of 3 = On
13 use_count = 1
14 status of 2 = On
15 status of 3 = On
16 use_count = 1
17 status of 1 = On
18 status of 3 = On
19 Destroying Controller1
20 Destroying Controller2
21 Destroying Controller3

<2> 关于weak_ptr:

weak_ptr类模板存储一个shared_ptr管理的对象的<弱引用>,即可以访问shared_ptr拥有的对象,但是不参与引用计数。如果程序中需要观察某个对象的状态,最好使用weak_ptr。同时weak_ptr也可以断开shared_ptr对象之间的循环引用。为了访问这个对象,可以使用shared_ptr构造函数将weak_ptr转换为一个shared_ptr(也可以使用weak_ptr的成员函数lock来转换)。如果shared_ptr管理的对象已经被析构,此时使用转换操作,那么shared_ptr的转换构造将抛出boost::bad_weak_ptr异常,而weak_ptr::lock将返回一个空的shared_ptr。

与shared_ptr相比,weak_ptr提供了非常有限的操作,因为在多线程程序中操作weak_ptr比较危险。shared_ptr中有一个get函数用于返回一个原始指针,如下是一种错误的用法:

shared_ptr<int> p(new int(5));

weak_ptr<int> q(p);

// ...

if (int* r = q.get())

{

    // use *r

}

如果在if语句后,使用r前,有另一个线程执行了:p.reset(),那么r就变为了空悬指针(dangling pointer),解决方法是利用weak_ptr中的lock函数创建一个q的临时shared_ptr:

shared_ptr<int> p(new int(5));

weak_ptr<int> q(p);

// ...

if (shared_ptr<int> r = q.lock())

{

    // use *r

}



 

你可能感兴趣的:(shared_ptr & weak_ptr)