> 文章列表 > c++ std::enable_shared_from_this作用

c++ std::enable_shared_from_this作用

c++ std::enable_shared_from_this作用

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 构造了一个智能指针进行返回,执行结果如下:
c++ std::enable_shared_from_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有一个在堆上创建的成员,我们再来看一下运行结果:
c++ std::enable_shared_from_this作用
可以看到程序再运行到最后时刻崩溃了,报错: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;
}

运行结果如下:
c++ std::enable_shared_from_this作用

可以看到,此时两个智能指针的引用计数都为2,这两个智能指针指向了相同的资源。在 main 函数退出后,两个智能指针依次释放,引用计数依次减一,直至为0,资源成功释放。

推荐一个零声学院免费教程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习: