在 C++ 中需要自己來(lái)處理內(nèi)存,稍微處理不當(dāng),就會(huì)存在非常郁悶的內(nèi)存泄漏問(wèn)題
還好,現(xiàn)在 C++ 中推出了強(qiáng)大的智能指針,即 smart_ptr ,本文先稍微介紹一下 smart_ptr ,然后具體說(shuō)說(shuō) shared_ptr 和 weak_ptr ,特別是 enable_shared_from_this 和 shared_from_this
除了標(biāo)準(zhǔn)庫(kù)中的 auto_ptr 之外
在 boost 或者 tr1 中的 smart_ptr 主要是有下面幾種
- scoped_ptr
- scoped_array
- shared_ptr
- shared_array
- intrusive_ptr
- weak_ptr
這些里面最難理解的是綜合應(yīng)用了 weak_ptr 和 shared_ptr 的 enable_shared_from_this 類,在該類中定了成員函數(shù) shared_from_this() ,返回 shared_ptr<T> 。這個(gè)函數(shù)僅在 shared_ptr<T> 的構(gòu)造函數(shù)被調(diào)用之后才能使用。原因是 enable_shared_from_this::weak_ptr 并不在構(gòu)造函數(shù)中設(shè)置(此處的構(gòu)造函數(shù)指的是類型 T 的構(gòu)造函數(shù)),而是在 shared_ptr<T> 的構(gòu)造函數(shù)中設(shè)置(此處的構(gòu)造函數(shù)指的是類型 shared_ptr<T> 的構(gòu)造函數(shù))。
在下面的代碼中:
- #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() 成員函數(shù),則會(huì)輸出 a 和 b 的 use_count() 都為 1 ,然后調(diào)用 2 次類型 Ansible 的析構(gòu)函數(shù),若添加了該成員函數(shù),在 a 和 b 的 use_count() 輸出為 2 ,只是調(diào)用一次 Ansible 的析構(gòu)函數(shù)。原因是 enable_shared_from_this 里面在 shared_ptr<T> 的時(shí)候構(gòu)造了一個(gè) weak_ptr 類,而 weak_ptr 只是監(jiān)視,不增加引用計(jì)數(shù)
(下面是轉(zhuǎn)載: http://huyuguang1976.spaces.live.com/blog/cns!2A9E272E3C33AFF1!185.entry )
所以如下代碼是錯(cuò)誤的:
class D:public boost::enable_shared_from_this<D>
{
public:
D()
{
boost::shared_ptr<D> p=shared_from_this();
}
};
原因很簡(jiǎn)單,在 D 的構(gòu)造函數(shù)中雖然可以保證 enable_shared_from_this<D> 的構(gòu)造函數(shù)已經(jīng)被調(diào)用,但正如前面所說(shuō), weak_ptr 還沒(méi)有設(shè)置。
如下代碼也是錯(cuò)誤的:
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();
}
錯(cuò)誤原因同上。
如下代碼是正確的:
void main()
{
boost::shared_ptr<D> d(new D);
d->func();
}
這里 boost::shared_ptr<D> d(new D) 實(shí)際上執(zhí)行了 3 個(gè)動(dòng)作:首先調(diào)用 enable_shared_from_this<D> 的構(gòu)造函數(shù);其次調(diào)用 D 的構(gòu)造函數(shù);最后調(diào)用 shared_ptr<D> 的構(gòu)造函數(shù)。是第 3 個(gè)動(dòng)作設(shè)置了 enable_shared_from_this<D> 的 weak_ptr ,而不是第 1 個(gè)動(dòng)作。這個(gè)地方是很違背 c++ 常理和邏輯的,必須小心。
結(jié)論是,不要在構(gòu)造函數(shù)中使用 shared_from_this ;其次,如果要使用 shared_ptr ,則應(yīng)該在所有地方均使用,不能使用 D d 這種方式,也決不要傳遞裸指針。
另解:::::
struct X
{
boost::shared_ptr<X> getX()
{
boost::shared_ptr<X> r ;//????如何實(shí)現(xiàn)
return r;
}
};
要得到X的智能指針,只是在對(duì)象指針是受shared_ptr保護(hù)的基礎(chǔ)上的,舉例如下:
void test_X()
{
{
X x;
boost::shared_ptr<X> px = x.getX();//錯(cuò)誤
}
{
X* x = new X();
boost::shared_ptr<X> px = x->getX();//錯(cuò)誤
}
{
boost::shared_ptr<X> x (new X());
boost::shared_ptr<X> px = x->getX();//正確
}
}