enable_shared_from_this 是什么
std::enable_shared_from_this 是一个类模板,用来返回指向当前对象的shared_ptr智能指针。在说明它的作用前我们可以看一下如下代码:
demo.cpp
#include <memory> #include <iostream> class A { public: A() { std::cout << "A()" << std::endl; } ~A() { std::cout << "~A()" << std::endl; } std::shared_ptr<A> getSharedPtr() { std::shared_ptr<A> ptr(this); return ptr; } }; int main() { std::shared_ptr<A> ptr1(new A()); std::shared_ptr<A> ptr2 = ptr1->getSharedPtr(); return 0; }
类 A 中有一个函数 getSharedPtr() 函数,用来返回指向当前对象的一个shared智能打针。其实就是用 this 构造了一个智能指针进行返回,执行结果如下:
看着好像没什么问题,别着急,再看下一个例子:
class B { public: B() { m_age = new int(10); std::cout << "B()" << std::endl; } ~B() { std::cout << "~B()" << std::endl; if (m_age){ delete m_age; m_age = nullptr; } } std::shared_ptr<B> getSharedPtr() { std::shared_ptr<B> ptr(this); return ptr; } private: int* m_age; }; int main() { std::shared_ptr<B> ptr1(new B()); std::shared_ptr<B> ptr2 = ptr1->getSharedPtr(); std::cout << ptr1.use_count() << std::endl; // 输出引用计数 std::cout << ptr2.use_count() << std::endl; // 输出引用计数 return 0; }
与类A不同的是,类B有一个在堆上创建的成员,我们再来看一下运行结果:
可以看到程序再运行到最后时刻崩溃了,报错:free(): invalid pointer,free 了无效的指针。我们应该能看到是重复释放的问题,这里我们将裸指针赋给了智能指针,这样做潜在的危险就是对象被多次释放。
细心的小伙伴肯定看到了,智能指针ptr1 和 ptr2 的引用计数都是 1,在程序执行结束的时候都会释放一次资源,导致程序崩溃。enable_shread_from_this 的作用就是解决这个问题,示例代码如下:
class C: public std::enable_shared_from_this<C> { public: C() { m_age = new int(10); std::cout << "C()" << std::endl; } ~C() { std::cout << "~C()" << std::endl; if (m_age){ delete m_age; m_age = nullptr; } } std::shared_ptr<C> getSharedPtr() { return shared_from_this(); } private: int* m_age; }; int main() { std::shared_ptr<C> ptr1(new C()); std::shared_ptr<C> ptr2 = ptr1->getSharedPtr(); std::cout << ptr1.use_count() << std::endl; std::cout << ptr2.use_count() << std::endl; return 0; }
运行结果如下:
可以看到,此时两个智能指针的引用计数都为2,这两个智能指针指向了相同的资源。在 main 函数退出后,两个智能指针依次释放,引用计数依次减一,直至为0,资源成功释放。