boost库 shared_from_this

来源:互联网 发布:js中删除一个对象集合 编辑:程序博客网 时间:2024/05/22 15:34

使用情景:

当类对象被 shared_ptr 管理时,需要在类自己定义的函数里把当前类对象作为参数传给其他函数时,这时需要传递一个 shared_ptr ,否则就不能保持 shared_ptr 管理这个类对象的语义(因为有一个 raw pointer 指向这个类对象,而 shared_ptr 对类对象的这个引用没有计数,很有可能 shared_ptr 已经把类对象资源释放了,而那个调用函数还在使用类对象——显然,这肯定会产生错误)。
怎么使用:
对一个类 A ,当我们希望使用 shared_ptr 来管理其类对象时,而且需要在自己定义的函数里把类对象 shared_ptr (为什么不用普通指针,当我们使用智能指针管理资源时,必须统一使用智能指针,而不能在某些地方使用智能指针某些地方使用 raw pointer ,否则不能保持智能指针的语义,从而产生各种错误)传给其他函数时,可以让类 A 从 enable_shared_from_this 继承:
class A : public boost::enable_shared_from_this<A> {
};
然后在类 A 中需要传递类对象本身 shared_ptr 的地方使用 shared_from_this 函数来获得指向自身的 shared_ptr 。

shared_from_this()在一个类中需要传递类对象本身shared_ptr的地方使用shared_from_this函数来获得指向自身的shared_ptr,它是enable_shared_from_this<T>的成员函数,返回shared_ptr<T>。

在类对象本身当中不能存储类对象本身的 shared_ptr ,否则类对象 shared_ptr 永远也不会为0了,从而这些资源永远不会释放,除非程序结束。


shared_from_this仅在shared_ptr<T>的构造函数被调用之后才能使用。原因是enable_shared_from_this::weak_ptr并不在enable_shared_from_this<T>构造函数中设置,而是在shared_ptr<T>的构造函数中设置。 
a) 如下代码是错误的:
[cpp] view plaincopyprint?
  1. class D:public boost::enable_shared_from_this<D>  
  2. {  
  3. public:  
  4.     D()  
  5.     {  
  6.         boost::shared_ptr<D> p=shared_from_this();  
  7.     }  
  8. };  
原因很简单,在D的构造函数中虽然可以保证enable_shared_from_this<D>的构造函数已经被调用,但正如前面所说,weak_ptr还没有设置。 
b) 如下代码也是错误的:
[cpp] view plaincopyprint?
  1. class D:public boost::enable_shared_from_this<D>  
  2. {  
  3. public:  
  4.     void func()  
  5.     {  
  6.         boost::shared_ptr<D> p=shared_from_this();  
  7.     }  
  8. };  
  9. void main()  
  10. {  
  11.     D d;  
  12.     d.func();  
  13. }  
错误原因同上。 
c) 如下代码是正确的:
[cpp] view plaincopyprint?
  1. void main()  
  2. {  
  3.     boost::shared_ptr<D> d(new D);  
  4.     d->func();  
  5. }  
这里boost::shared_ptr<D> d(new D)实际上执行了3个动作:
1. 首先调用enable_shared_from_this<D>的构造函数;
2. 其次调用D的构造函数;
3. 最后调用shared_ptr<D>的构造函数。
是第3个动作设置了enable_shared_from_this<D>的weak_ptr,而不是第1个动作。这个地方是很违背c++常理和逻辑的,必须小心。 

结论是:不要在构造函数中使用shared_from_this;其次,如果要使用shared_ptr,则应该在所有地方均使用,不能使用D d这种方式,也决不要传递裸指针。   
0 0
原创粉丝点击