colorful

zc qq:1337220912

 

enable_shared_from_this(转载)

在 C++ 中需要自己来处理内存,稍微处理不当,就会存在非常郁闷的内存泄漏问题

 

还好,现在 C++ 中推出了强大的智能指针,即 smart_ptr ,本文先稍微介绍一下 smart_ptr ,然后具体说说 shared_ptr 和 weak_ptr ,特别是 enable_shared_from_this 和 shared_from_this

 

除了标准库中的 auto_ptr 之外

在 boost 或者 tr1 中的 smart_ptr 主要是有下面几种

  • scoped_ptr
  • scoped_array
  • shared_ptr
  • shared_array
  • intrusive_ptr
  • weak_ptr

这些里面最难理解的是综合应用了 weak_ptr 和 shared_ptr 的 enable_shared_from_this 类,在该类中定了成员函数 shared_from_this() ,返回 shared_ptr<T> 。这个函数仅在 shared_ptr<T> 的构造函数被调用之后才能使用。原因是 enable_shared_from_this::weak_ptr 并不在构造函数中设置(此处的构造函数指的是类型 T 的构造函数),而是在 shared_ptr<T> 的构造函数中设置(此处的构造函数指的是类型 shared_ptr<T> 的构造函数)。

 

在下面的代码中:

 

Cpp代码
  1. #include <iostream>   
  2.   
  3. #include <string>   
  4.   
  5.     
  6.   
  7. #include <boost/shared_ptr.hpp>   
  8.   
  9. #include <boost/weak_ptr.hpp>   
  10.   
  11. #include <boost/enable_shared_from_this.hpp>   
  12.   
  13.     
  14.   
  15. using namespace std;   
  16.   
  17.     
  18.   
  19. struct Ansible   
  20.   
  21.   : public boost::enable_shared_from_this<Ansible>   
  22.   
  23. {   
  24.   
  25.     boost::shared_ptr<Ansible> get_shared()   
  26.   
  27.     {   
  28.   
  29.         boost::shared_ptr<Ansible> r(this);   
  30.   
  31.     
  32.   
  33.         return r;   
  34.   
  35.     }   
  36.   
  37.     
  38.   
  39.     ~Ansible()   
  40.   
  41.     {   
  42.   
  43.         cout<<"Destructor"<<endl;   
  44.   
  45.     }   
  46.   
  47. };   
  48.   
  49.     
  50.   
  51. int main(int argc,char* argv[])   
  52.   
  53. {   
  54.   
  55.     boost::shared_ptr<Ansible> a(new Ansible);   
  56.   
  57.     Ansible& r = *a;   
  58.   
  59.     //boost::shared_ptr<Ansible> b = r.get_shared();   
  60.   
  61.     boost::shared_ptr<Ansible> b = r.shared_from_this();   
  62.   
  63.     
  64.   
  65.     cout<<"Reference Number "<<a.use_count()<<" "<<b.use_count()<<endl;   
  66.   
  67.     
  68.   
  69.     return 0;   
  70.   
  71. }  
#include <iostream> #include <string> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> #include <boost/enable_shared_from_this.hpp> using namespace std; struct Ansible : public boost::enable_shared_from_this<Ansible> { boost::shared_ptr<Ansible> get_shared() { boost::shared_ptr<Ansible> r(this); return r; } ~Ansible() { cout<<"Destructor"<<endl; } }; int main(int argc,char* argv[]) { boost::shared_ptr<Ansible> a(new Ansible); Ansible& r = *a; //boost::shared_ptr<Ansible> b = r.get_shared(); boost::shared_ptr<Ansible> b = r.shared_from_this(); cout<<"Reference Number "<<a.use_count()<<" "<<b.use_count()<<endl; return 0; }

 

若不使用 shared_from_this() 成员函数,则会输出 a 和 b 的 use_count() 都为 1 ,然后调用 2 次类型 Ansible 的析构函数,若添加了该成员函数,在 a 和 b 的 use_count() 输出为 2 ,只是调用一次 Ansible 的析构函数。原因是 enable_shared_from_this 里面在 shared_ptr<T> 的时候构造了一个 weak_ptr 类,而 weak_ptr 只是监视,不增加引用计数

 

(下面是转载: http://huyuguang1976.spaces.live.com/blog/cns!2A9E272E3C33AFF1!185.entry

所以如下代码是错误的:

 

class D:public boost::enable_shared_from_this<D>

{

public:

    D()

    {

        boost::shared_ptr<D> p=shared_from_this();

    }

};

 

原因很简单,在 D 的构造函数中虽然可以保证 enable_shared_from_this<D> 的构造函数已经被调用,但正如前面所说, weak_ptr 还没有设置。

 

如下代码也是错误的:

 

class D:public boost::enable_shared_from_this<D>

{

public:

    void func()

    {

        boost::shared_ptr<D> p=shared_from_this();

    }

};

 

void main()

{

    D d;

    d.func();

}

 

错误原因同上。

 

如下代码是正确的:

 

void main()

{

    boost::shared_ptr<D> d(new D);

    d->func();

}

 

这里 boost::shared_ptr<D> d(new D) 实际上执行了 3 个动作:首先调用 enable_shared_from_this<D> 的构造函数;其次调用 D 的构造函数;最后调用 shared_ptr<D> 的构造函数。是第 3 个动作设置了 enable_shared_from_this<D> 的 weak_ptr ,而不是第 1 个动作。这个地方是很违背 c++ 常理和逻辑的,必须小心。

 

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


另解:::::
struct X

{

         boost::shared_ptr<X> getX()

{

         boost::shared_ptr<X> r ;//????如何实现

         return r;

}

};

 

要得到X的智能指针,只是在对象指针是受shared_ptr保护的基础上的,举例如下:

void test_X()

{

         {

X x;

                  boost::shared_ptr<X> px = x.getX();//错误

}

         {

X* x = new X();

boost::shared_ptr<X> px = x->getX();//错误

}

         {

boost::shared_ptr<X>  x (new X());

boost::shared_ptr<X> px = x->getX();//正确

}

}

posted on 2012-06-22 22:41 多彩人生 阅读(453) 评论(0)  编辑 收藏 引用 所属分类: boost


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

统计

常用链接

留言簿(3)

随笔分类

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜