在 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> 的构造函数)。
在下面的代码中:
- #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;
-
- }
#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();//正确
}
}