15

有人可以用几句简洁的话总结一下shared_from_this<>()应该如何使用 boost 智能指针,特别是从使用 bind 函数在 io_service 中注册处理程序的角度来看。

编辑:一些回复要求提供更多背景信息。基本上,我正在寻找“陷阱”,人们使用这种机制观察到的反直觉行为。

4

5 回答 5

33

我遇到的最大“问题”是从构造函数调用 shared_from_this 是非法的。这直接遵循以下规则:对象的 shared_ptr 必须存在才能调用 shared_from_this。

于 2010-09-02T21:08:06.747 回答
14

据我了解,有时在您的代码中,您希望一个类为其shared_ptr自身提供 up ,以便您的代码的其他部分可以在构建类的对象后获取 shared_ptr 。

问题是,如果你的类只有一个shared_ptr<>to 作为成员变量,它永远不会被自动破坏,因为总是有“最后一个引用”挂在它自己身上。继承 fromenable_shared_from_this为您的类提供了一个自动方法,该方法不仅返回 a shared_ptr,而且仅将弱共享指针作为成员变量保存,以免影响引用计数。这样,当最后一个对它的引用消失时,你的类将像往常一样被释放。

我从未使用过它,但这是我对其工作原理的理解。

于 2010-09-02T17:45:34.533 回答
11

shared_from_this<>如果对象想要访问shared_ptr<>指向自身的指向,则使用此方法。

通常一个对象只知道隐式this指针,但不知道任何shared_ptr<>管理它。此外,this不能轻易地转换为shared_ptr<>与其他现有shared_ptr<>实例共享所有权的对象,因此对象没有简单的方法来获得shared_ptr<>对自身的有效性。

shared_from_this<>可以用来解决这个问题。例如:

struct A : boost::enable_shared_from_this<A> {
   server *io;
   // ...

   void register_self() {
      io->add_client(shared_from_this());
   }
};
于 2010-09-02T18:01:55.920 回答
7

boost::asio::io_service 析构函数文档很好地解释了它

上述销毁顺序允许程序通过使用 shared_ptr<> 来简化其资源管理。如果对象的生命周期与连接的生命周期(或某些其他异步操作序列)相关联,则对象的 shared_ptr 将绑定到与其关联的所有异步操作的处理程序中。这工作如下:

  • 当单个连接结束时,所有关联的异步操作都完成。相应的处理程序对象被销毁,并且对对象的所有 shared_ptr 引用都被销毁。
  • 要关闭整个程序,调用 io_service 函数 stop() 以尽快终止任何 run() 调用。上面定义的 io_service 析构函数会销毁所有处理程序,导致对所有连接对象的所有 shared_ptr 引用都被销毁。

通常,您的对象将链接异步操作,其中处理程序使用boost::bindand绑定到成员函数boost::shared_from_this()。有一些使用这个概念的例子。

于 2010-09-02T18:53:50.117 回答
2

上面的一些评论中缺少东西。这是一个帮助我的例子:

提升 enable_shared_from_this 示例

对我来说,我一直在为糟糕的弱指针错误而苦苦挣扎。您必须以 shared_ptr 方式分配对象:

class SyncSocket: public boost::enable_shared_from_this<SyncSocket>

并像这样分配一个:

boost::shared_ptr<SyncSocket> socket(new SyncSocket);

然后您可以执行以下操作:

socket->connect(...);

许多示例向您展示了如何使用 shared_from_this() ,如下所示:

boost::asio::async_read_until(socket, receiveBuffer, haveData,
        boost::bind(&SyncSocket::dataReceived, shared_from_this(), boost::asio::placeholders::error));

但对我来说缺少的是使用 shared_ptr 来分配对象。

于 2019-08-13T16:36:34.797 回答