由于移动构造函数而删除的对象

Object deleted because of move constructor

本文关键字:删除 对象 构造函数 于移动 移动      更新时间:2023-10-16

>我正在尝试创建一个在专用线程中运行的函数从串行端口读取。但是我在传递连接时遇到问题到线程。我将代码简化为以下示例:

#include <thread>
#include <boost/asio.hpp>
template <typename Port>
void serial_read( Port& port) {}
int main()
{
  boost::asio::io_service serial_io;
  boost::asio::serial_port port( serial_io );
  port.open( "/dev/ttyUSB0" );
  std::thread s( serial_read<boost::asio::serial_port>, port );
  return 0;
}

但是,我收到以下错误消息:

/usr/include/c++/4.7/tuple:128:25: error: use of deleted function ‘boost::asio::basic_serial_port<>::basic_serial_port(const boost::asio::basic_serial_port<>&)’
In file included from /usr/include/boost/asio.hpp:25:0,
                 from main.cpp:2:
/usr/include/boost/asio/basic_serial_port.hpp:47:7: note: ‘boost::asio::basic_serial_port<>::basic_serial_port(const boost::asio::basic_serial_port<>&)’ is implicitly declared as deleted because ‘boost::asio::basic_serial_port<>’ declares a move constructor or move assignment operator

错误消息非常清楚。我正在尝试使用对象它不存在,因为它已被删除,因为移动构造函数的声明。但我仍然不明白这是怎么回事以及如何正确操作。有人可以开导我?

您没有正确读取错误。它告诉你boost::asio::basic_serial_port复制构造函数delete d。这意味着不能使用复制构造函数。它与要删除的对象无关。复制构造函数delete d 的原因是因为定义了移动构造函数。

如果你真的需要传递对serial_read的引用,你需要将你的port对象包装在一个reference_wrapper中:

std::thread s( serial_read<boost::asio::serial_port>, std::ref(port) );

但是,如果您不保留port并将其用于其他任何操作(例如将相同的port对象传递给其他线程(,则应将port对象std::move到线程中:

std::thread s( serial_read<boost::asio::serial_port>, std::move(port) );

这还需要更改serial_read的定义以按值获取Port

template <typename Port>
void serial_read( Port port) {}

简单的解决方法(我相信,未经测试(是使用引用包装器(如果您确实需要在 main 和线程中维护对象(:

std::thread s(&serial_read<boost::asio::serial_port>,std::ref(port));

问题是std::thread(因为std::bind将创建一个带有参数副本的函子(,稍后将使用(没有参数(。基本上上面的调用类似于:

std::thread( std::bind(&serial_read<boost::asio::serial_port>,std::ref(port)) );

绑定对象中存储了每个参数的副本,这要求参数是可复制的。引用包装器的使用允许复制(复制包装器,不复制原始对象(。

如果您不需要维护 port 对象在 main 中有效,另一种选择是从它移动,以便允许实现从 main 中的对象移动,而不是复制到绑定对象中。