【问题标题】:Move constructor is not called with boost::asio::ip::tcp::socket不使用 boost::asio::ip::tcp::socket 调用移动构造函数
【发布时间】:2015-04-26 13:36:56
【问题描述】:

我认为下面的代码应该可以工作,但是会产生编译错误:

error C2248: 'boost::asio::basic_io_object<SocketService,true>::basic_io_object' : cannot access private member declared in class 'boost::asio::basic_io_object<SocketService,true>'

好像没有隐式调用move构造函数。

#include <thread>
#include <boost/asio.hpp>

void Func(boost::asio::ip::tcp::socket sock) {}

int main()
{
    boost::asio::io_service service;
    boost::asio::ip::tcp::socket sock(service);
    std::thread(Func, std::move(sock)).detach(); // error C2248
    //Func(std::move(sock)); // OK
    return 0;
}

我也尝试按照this question 中的建议定义 BOOST_ASIO_HAS_MOVE,但没有成功。

有什么解决方法吗?

用 VS2013 update 3 和 boost 1.56.0 进行了实验。

【问题讨论】:

  • 问题是std::thread在内部存储参数,这意味着当调用线程函数时,参数是按值传递的
  • 很抱歉,如果我的回答不准确,但我不能 100% 确定您想要了解什么。我根据“我认为这段代码应该可以工作”来写我的答案,然后继续解释为什么它不能以及它应该如何工作。如果您的问题不是关于使用 boost::asio 创建一个正常运行的程序,而是关于移动语义以及它们如何应用一些抽象概念来处理获取某物所有权的线程,那么请澄清。
  • @TechnikEmpire 抱歉含糊不清。正如你所说,当我想通过 std::thread 将套接字的所有权移动到 Func 时,我的意图是关于移动语义的行为,而不是关于 boost::asio 的使用。

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


【解决方案1】:

这是编译器的一个已知错误。 bug ticket 提到这已在 VS 2015 RTM 中修复。

作为一种解决方法,请考虑创建一个垫片来移动套接字。下面是一个小例子demonstrating这种做法:

#include <memory>
#include <thread>
#include <boost/asio.hpp>

void Func(boost::asio::ip::tcp::socket) {}

int main()
{
  boost::asio::io_service io_service;
  auto socket = std::make_shared<boost::asio::ip::tcp::socket>(
      std::ref(io_service));

  // Use a shim to move the socket to Func.
  std::thread func_thread([socket]() {
    return Func(std::move(*socket));
  });
  socket.reset();

  // Guarantee the io_service remains alive until after
  // its I/O objects have been destroyed.
  func_thread.join();
}

另外,请注意,某种形式的同步需要使io_service 保持活动状态,直到相关 I/O 对象销毁。

【讨论】:

    猜你喜欢
    • 2021-04-04
    • 1970-01-01
    • 1970-01-01
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 2017-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多