为什么可以重新使用boost :: asio :: tcp :: socket?

时间:2018-07-31 16:13:37

标签: c++ c++11 boost boost-asio move-semantics

下面是一些代码from a boost::asio example。如果在处理程序底部进行的递归调用将在下一次接受时将相同的socket_交出,那么在构造chat_session时为何可以移动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_;
};

3 个答案:

答案 0 :(得分:3)

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

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,状态是未初始化的套接字,可以用于新连接。

答案 1 :(得分:1)

您是正确的,移动后套接字对象不可用。

但是 调用lambda的代码将创建一个 new 套接字,并使用该新套接字初始化变量declare @TwoDigitYearCutoff int = 90; select [date], ConvertedDate = convert(date, case when convert(int, substring([date], 5, 2)) <= @TwoDigitYearCutoff then '20' else '19' end + substring([date], 5, 2) + substring([date], 3, 2) + substring([date], 1, 2), 112) from @Table; 。因此,下次调用lambda时,实际上是一个不同套接字。

答案 2 :(得分:1)

该标准规定,“移出”对象必须至少处于有效的未指定状态。

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

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