在類的內(nèi)部獲取shared_ptr是在所難免的。
舉個(gè)例子:
在日常c++編程中蓄诽,為了更好的管理資源就漾,我們通常借助shared_ptr來達(dá)到對(duì)資源的自動(dòng)管理粱坤。由于其原理是通過過跟蹤引用計(jì)數(shù)實(shí)現(xiàn)的店印,也就是說在使用了shared_ptr后就不能再使用裸指針this冈在。比如說在類的內(nèi)部直接使用std::shared_ptr<XX>(this),就會(huì)導(dǎo)致智能指針失效按摘。
常見的場(chǎng)景:
通過std::bind生成functor函數(shù)傳遞給其他實(shí)例時(shí)(暴露了this)包券,當(dāng)其他實(shí)例調(diào)用functor函數(shù)時(shí)纫谅,該實(shí)例有可能已經(jīng)被析構(gòu),會(huì)引起異常溅固。
首先我們看下shared_ptr的用法付秕,
class Test{
public:
Test() {
a = 123;
std::cout << "construct\n";
};
void func() {
std::cout << "test func called data="<< a << "\n";
};
~Test() {
std::cout << "destroy\n";
};
private:
int a;
};
int main()
{
{
std::shared_ptr<Test> b(new Test());
b->func();
}
}
// construct
// test func called data=123
// destroy
在某些情況,當(dāng)我們?cè)趂unc內(nèi)部將this傳遞給其他對(duì)象后侍郭,由于使用了裸指針询吴,導(dǎo)致shared_ptr無法正常跟蹤計(jì)數(shù)。最終Test會(huì)被析構(gòu)兩次亮元,導(dǎo)致未定義行為猛计。下面的代碼展示了這個(gè)問題。
#include <memory>
#include <iostream>
class Test
{
public:
std::shared_ptr<Test> getptr() {
return std::shared_ptr<Test>(this);
}
~Test() { std::cout << "Test::~Test() called" << std::endl; }
};
int main()
{
std::shared_ptr<Test> a(new Test());
std::shared_ptr<Test> b = a->getptr();
std::cout << "a.use_count() = " << a.use_count() << std::endl; // 1
std::cout << "b.use_count() = " << b.use_count() << std::endl; // 1
}
使用 enable_shared_from_this來修正這個(gè)問題
#include <memory>
#include <iostream>
class Test :public std::enable_shared_from_this<Test>
{
public:
std::shared_ptr<Test> getptr() {
return shared_from_this();
}
~Test() { std::cout << "Test::~Test() called" << std::endl; }
};
int main()
{
std::shared_ptr<Test> a(new Test());
std::shared_ptr<Test> b = a->getptr();
std::cout << "a.use_count() = " << a.use_count() << std::endl; // 2
std::cout << "b.use_count() = " << b.use_count() << std::endl; // 2
}
這樣shared_ptr就能正確的取得計(jì)數(shù)苹粟。避免了在內(nèi)部無法正確取得shared_ptr的困境有滑。