首页 > Note > 关于 enable_shared_from_this

关于 enable_shared_from_this

2019年5月16日 发表评论 阅读评论

一. 引入

简单地说: enable_shared_from_this 是为了解决 在类的内部获取自己的 shared_ptr 这件事情而存在的。

众所周知, 每一个对象都能通过this 指针来访问自己的地址。this 指针也是所有成员函数的隐含参数。然而有些时候,我们需要的不仅是 this,而是一个 "this的智能指针"。

这里有一个常见的场景:

代码如上:在异步方法 DoSth_Async() 中调用了成员方法 OnDo(bool) . 这里存在一个问题: 当 OnDo() 被调用的时候,该类的是否还在生存中:

智能指针 ptr 在出作用域后立即被释放。所以当 OnDo() 被调用的时候,其所在的对象实际已经被释放了。如果确保在 OnDo() 被调用的时候,该对象仍然在生命周期内呢?一个方便的方法便上在构建线程的时候,将该对象的 shared_ptr 传入到线程。在该线程的生命周期内,该对象就会一直存在。这是一种利用 shared_ptr 的 保活机制

此时, enable_shared_from_this 就有存在的必要了:

enable_shared_from_this 是一个模板类。它一般用作基类,它的成员 shared_from_this() weak_from_this() 可以使继承此类的类从当前对象获取其本身的 shared_ptr 或者 weak_ptr 并且增加引用计数.

我们直接使用 this 指针来构建自身的 shared_ptr 不可以吗,就像下面代码所表现的?

这种方法在使用的时候可能看不出问题,但是在对象析构的时候将会出现问题:一个对象将被释放两次,在 DoSomthing() 方法结束后它将释放一次,在 main() 函数完成后又将释放一次。究其原因,GetSelf() 构造智能指针时,其引用计数并没有自增。

二. 原理

enable_shared_from_this 位于 <memory> 头文件中,其实现非常简单:

其中友元 _Enable_shared_from_this1() 将会被类 shared_ptr 调用。在这个友元里,会尝试着给私有成员 _Wptr 赋。当 shared_from_this() 被调用时,使用 _Wptr 构造一个 shared_ptr ,此时引用计数增 1 。

三. 陷阱

1. 在原生指针的对象里调用了 shared_from_this

如下代码:

由于没有使用 shared_ptr, 友元 _Enable_shared_from_this1() 不会被调用,此时 _Wptr 是 empty 的。如果强行调用 shared_from_this() 将会引发异常 exception : std::bad_weak_ptr

2. 过早调用 shared_from_this()

代码如下: 在构造函数中调用了 shared_from_this() 时, 还没有给 _Wptr 赋值。此时会引发 exception : std::bad_weak_ptr

3. 关于继承

在一棵继承树里重复的继承 std::enable_shared_from_this 将引发编译错误。如果需要在子类中使用 shared_from_this可以这么写:

 

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.