…
1. 介绍
关于智能指针 shared_ptr 很有意思的一个问题。
可以用 std::shared_ptr 将裸指针封装起来,变成带引用计数的智能指针,当引用计数为0,C++会自动把裸指针指向的内存回收。
先定义一个类
1 | class A |
这里p是裸指针,sp是智能指针,管理p:
1 | int *p = new A(); |
现在新建个sp2,可以跟sp一起管理p了
1 | int *p = new A(); |
有个问题,如果再用sp2直接去管理p,会出现什么行为?
1 | int *p = new A(); |
因为 sp 和 sp2 是两个不相关的变量,不知道对方也在管理着p,在各自析构的时候,会导致重复释放p。相当于free(p)了两次,程序会挂掉。
这里的问题是:如何让p的所有权,由1组相关的shared_ptr来管理,这些shared_ptr使用引用计数,相互知道对方;而不是由两组shared_ptr来管理,各自维护一套引用计数。
那么如何让sp2知道之前有个sp在管理p呢?一种方法是用sp去构造sp2,还有一种方法是通过shared_from_this
。
1 | // 1. A继承std::enable_shared_from_this<A>模板类 |
2. 使用场景
如果一个类使用shared_ptr来管理,但是类中的成员函数需要将该对象作为参数传递给其他外部函数,就可以使用shared_from_this()
来处理。更具体些,在类内部需要调用异步函数的时候,异步函数执行的时间点不确定,在类内调用的时候可能只是设置个lambda,或者使用 std::bind 绑定一下,这时候需要将该对象使用 shared_ptr<> 传递给异步函数,做保活,保证异步函数在调用的时候,本对象还存活。
为什么不直接传递裸指针?
为了统一用智能指针来管理对象。只要在外部使用到该类的地方,都使用智能指针来处理。
为什么不使用 shared_ptr<A>(this)?
前边已经说过了,会产生两组不相关的shared_ptr,导致释放两次该对象。
使用示例如下:
1 | class A; |
3. 如何实现 shared_from_this()
大致如下:
1 | shared_ptr<A *a> { |
在构造shared_ptr<A> 的时候,判断A是否继承了 std::enable_shared_from_this,如果继承,就将 shared信息保存到 std::enable_shared_from_this 的一个成员 weak_ptr_obj 中。然后再调用 shared_from_this() 的时候,根据 weak_ptr_obj 从保存的信息中获取一个 shared_ptr。
参考
- C++11新特性之十:enable_shared_from_this
- shared_ptr 之shared_from_this
- 《inux多线程服务器端编程》 $1.11.1