对enable_shared_from_this有什么需求?

时间:2016-03-16 16:06:18

标签: c++ c++11 boost shared-ptr

我是C ++ 11的新手,我遇到了enable_shared_from_this。我不明白它想要达到的目的是什么?所以我有一个使用enable_shared_from_this的程序。

struct TestCase: enable_shared_from_this<TestCase>
{
std::shared_ptr<testcase> getptr() {
    return shared_from_this();
}

~TestCase() { std::cout << "TestCase::~TestCase()"; }
};


int main()
{
std::shared_ptr<testcase> obj1(new TestCase);
std::shared_ptr<testcase> obj2 = obj1->getptr();
// The above can be re written as below
//  std::shared_ptr<testcase> obj2 = shared_ptr<testcase>(obj1);
}

我的问题是当我需要一个指向'this'的指针时,为什么不使用obj本身。为什么要从该类的函数返回'this',比如使用getptr()然后返回shared_from_this()???? 我不明白。

第二个问题,如果不使用enable_shared_from_this,为什么dtor被调用两次会产生问题,一个崩溃!!!!

我可以绕过使用enable_shared_from_this的另一种方法是这样的。 在TestCase类中添加它

  std::shared_ptr getptr1(shared_ptr obj) {
   return std::shared_ptr(obj);
  }

从主要打电话给这个:

  std::shared_ptr bp2 = bp1->getptr1(bp1);

完成了。我们不需要enable_shared_from_this。为什么在地球上我们需要它?

2 个答案:

答案 0 :(得分:6)

shared_ptr管理两件不同的事情。它有一个指向其数据的指针,以及一个指向引用计数块的指针。

引用计数模块中有一个强计数器,一个弱计数器和一个销毁操作。

当你std::shared_ptr<X>(pX)时,它会创建一个新的引用计数块,当最后一个(强)引用消失时,它会删除pX对象。

当你std::shared_ptr<X>(this)时会发生同样的事情。

因此,如果您将对象放在std::shared_ptr两个不同的位置中,则必须不同的引用计数块,并且它们都< / em>想要在它们消失时销毁它。

enable_shared_from_this<X>会改变其工作原理。当您创建指向从其继承的对象的共享指针时,它会在std::weak_ptr<X>内存储enable_shared_from_this<X>。弱指针存储指向上述引用计数块的指针,但仅“保持”弱引用(不是强引用)。

然后,当您调用shared_from_this()时,它会对该弱指针执行.lock()并使用创建的旧指针的引用计数块返回共享指针(如由weak_ptr存储。

现在,上面是它可以做的示例实现:标准强制要求行为,而不是实现,weak_ptr是实现它的可能方式。类似地,引用计数块细节仅是示例实现。

核心问题是包含相同指针的两个独立共享指针将尝试独立管理指针的生命周期。 enable_shared_from_this使第一个智能指针的引用计数块被后来的shared_from_this()返回值使用。

答案 1 :(得分:3)

简短回答:当您需要在对象内部使用现有的共享指针保护enable_shared_from_this对象时,您需要this

在对象之外,您可以简单地分配和复制shared_ptr,因为您按原样处理shared_ptr变量。但是当你在一个类成员中时,如果你需要使用指向self对象的共享指针(而不是普通的this)并且在该方法的参数中没有这样的共享指针那么{{1}什么会帮助你。 使用shared_from_this()绝对不安全,因为在同一个对象上不能有两个共享指针。虽然std::make_shared(this)是安全的,因为它使用shared_from_this()来“解析”现有的weak_ptr

为了能够使用shared_ptr,您必须先在类定义中使用shared_from_this(),这会为您的班级添加enable_shared_from_this方法。

注意,shared_from_this()不能在类构造函数中使用!那时shared_from_this()尚不存在,因此shared_ptr无法解析任何现有指针。

当一个人需要共享指针shared_from_this()而不仅仅是this的时候和原因时,这是另一个问题。例如,它广泛用于异步编程中,用于回调绑定。