为什么这个boost::asio::tcp::socket可以重复使用?

Why can this boost::asio::tcp::socket be re-used?

下面是一些代码 from a boost::asio example。为什么在构造 chat_session 时可以移动 socket_ 成员,如果处理程序底部的递归调用将在下次接受发生时传递相同的 tcp::socket ?我以为移动操作后,一个对象不再安全使用。

class chat_server
{
public:
  chat_server(boost::asio::io_service& io_service,
      const tcp::endpoint& endpoint)
    : acceptor_(io_service, endpoint),
      socket_(io_service)
  {
    do_accept();
  }

private:
  void do_accept()
  {
    acceptor_.async_accept(socket_,
        [this](boost::system::error_code ec)
        {
          if (!ec)
          {
            std::make_shared<chat_session>(std::move(socket_), room_)->start();
          }

          do_accept();
        });
  }

  tcp::acceptor acceptor_;
  tcp::socket socket_;
  chat_room room_;
};

你是对的,移动后套接字对象不可用。

但是 调用您的 lambda 的代码将创建一个 new 套接字并初始化您的变量socket_ 使用那个新插座。因此,下次调用 lambda 时,它实际上是一个 不同的 套接字。

该代码等效于执行以下操作:

some_class o;
while ( true )
{
  // assign a new instance of some_class to the o variable, calling o.bar() is valid
  o = some_class(...);
  foo(std::move(o));
  // o is no longer valid calling o.bar() would fail
}

async_accept 的调用将套接字重新初始化为可以使用的有效值。移动的对象处于未指定(但有效)状态,由该对象的实现者决定该状态是什么。在 asio::tcp::socket 的情况下,状态是一个未初始化的套接字,可用于新连接。

标准规定 "moved-from" 对象必须至少处于有效的未指定状态。

移出的套接字可以安全使用,因为它的状态在文档中明确指定:

Following the move, the moved-from object is in the same state as if constructed using the basic_stream_socket(io_context&) constructor.