enable_shared_from_this<S> 什么时候有用?

When is enable_shared_from_this<S> useful?

我一直在努力理解从 enable_shared_from_this 继承的有用性,尽管那里对这种机制的工作原理做了一些解释。我在 post 上找不到这个问题的答案,所以我把它贴在这里。

在其中一个例子中。以下示例作为不良做法给出。我理解原因是两个共享指针彼此不认识,一旦其中一个共享指针超出范围,资源将被销毁。

struct S
{
  shared_ptr<S> dangerous()
  {
     return shared_ptr<S>(this);   // don't do this!
  }
};

int main()
{
   shared_ptr<S> sp1(new S);
   shared_ptr<S> sp2 = sp1->dangerous();
   return 0;
}

我的问题是用户为什么不这样做

 shared_ptr<S> sp2 = sp1;

那不也只会增加引用计数吗?会好吗?是否给出了该示例,以防万一 class 无法访问 sp1 并且需要 return 返回 shared_ptr

核心问题在于,出于某种原因,并非代码库中的每个共享指针都"known" 指向其余代码。

如果您可以访问已经给定的 shared_ptr,您应该始终像您所写的那样使用 shared_ptr<S> sp2 = sp1;。使用 std::enable_shared_from_this.

绝对好而且更好

举个例子:

struct S: std::enable_shared_from_this<S>
{   
    std::shared_ptr<S> getPtr() { return shared_from_this(); }
};  

// Here we have no interface for providing a shared_ptr, maybe
// code that we can't change or maintain or comes as callback from
// a library we want to use
void f( S* s ) 
{   
    // here we have no access to shared_ptr<S>...
    // so we need to have access to the unique counting instance
    // of all other shared_ptr which are pointing to this object
    std::shared_ptr<S> p3 = s->getPtr();
    std::cout << p3.use_count() << std::endl;

    // do some stuff....

}

int main()
{
    std::shared_ptr<S> p1 = std::make_shared<S>();
    std::cout << p1.use_count() << std::endl;

    // This example is useless, as you can directly use p1
    std::shared_ptr<S> p2 = p1->getPtr();
    std::cout << p1.use_count() << std::endl;
    std::cout << p2.use_count() << std::endl;

    // But if we have to use a interface, which is not providing access via shared_ptr like this:
    f(p1.get());
}  

这里解决的关键问题是简单地访问连接我们系统 IF 周围所有其他 shared_ptr 的公共 "handle"!我们根本无法访问任何 shared_ptr!

我们无法访问我们对象的任何现有 shared_ptr 的原因可能有很多,例如:使用只允许原始指针但我们想在其余部分使用共享指针的旧接口我们的代码,使用库中的回调,这些库也只支持原始指针等。

使用 std::enable_shared_from_this<S> 有一些缺点:

您的接口不能再使用 const S*,因为创建一个新的 shared_ptr 将修改 std::enable_shared_from_this 的数据,它现在是您的 [=] 的基础 class 37=] 或结构。它还会增加对象的大小。