Asio:示例中使用自共享指针

时间:2016-05-04 19:40:28

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

查看Asio库的示例this one for example(例如,第37行),我发现有时候他们会创建一个共享指针(他们自己命名),并在lambda中捕获它他们称之为asio功能,但我不明白它的用途是什么。我甚至没有看到它被使用过。

那么,他们为什么要这样做?

相关代码:

..在服务器类中......(创建会话的地方)

if (!ec)
{
    std::make_shared<session>(std::move(socket_))->start();
}

... session::start()会员方法:

void start()
  {
    do_read();
  }

... session::do_read()成员方法(我感兴趣的地方):

void do_read()
  {
    auto self(shared_from_this());                    // <<< ---WHY THIS??????
    socket_.async_read_some(asio::buffer(data_, max_length),
        [this, self](std::error_code ec, std::size_t length)
        {
          if (!ec)
          {
            do_write(length);
          }
        });
  }

2 个答案:

答案 0 :(得分:5)

std::enable_shared_from_this<>的目的是从拥有调用std::shared_ptr成员函数的对象的shared_from_this句柄创建额外的std::shared_ptr

if (!ec)
{
     std::make_shared<session>(std::move(socket_))->start();
}

以上 - ^^^ - 是创建session的{​​{3}}。正如您所看到的,std::shared_ptr返回的std::make_shared将在;处销毁,这也应该会破坏session创建的...

但是因为line方法调用start()定义为...

void do_read()
  {
    auto self(shared_from_this());
    socket_.async_read_some(asio::buffer(data_, max_length),
        [this, self](std::error_code ec, std::size_t length)
        {
          if (!ec)
          {
            do_write(length);
          }
        });
  }

self会增加shared_ptr引用计数。所以创建的do_read()的破坏不会破坏对象,相反,它会将self留作创建对象的引用。

还要知道一个Lambda可以比它的调用者更长... boost::asio::async_write是一个异步方法,在复制它的参数后立即返回。在您到达session生命终结之前,传递的lambda可能无法执行。因此,如果没有std::shared_ptr创建的额外shared_from_this,析构函数将运行。额外的shared_ptr阻止session的析构函数运行,直到调用lambda函数并且它的参数被破坏。

答案 1 :(得分:1)

您引用的lambda是从类对象捕获状态(例如this指针),并且它们需要确保对象在访问状态时仍处于活动状态。请记住,这些lambda是异步调用的,例如,当有数据准备好读取时。最初实例化类的函数和异步lambdas因此都共享类实例的所有权。

您是否阅读了this,如果没有,可能会有所帮助?