我正在尝试创建一个在专用线程中运行的函数 从串口读取。但是我无法通过连接 到线程。我将代码缩减为以下示例:
#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
错误信息非常清楚。我正在尝试使用一个对象 这是不存在的,因为它已被删除 移动构造函数的声明。但我还是不明白 这里发生了什么,以及如何正确地做到这一点。有人可以 赐教?
答案 0 :(得分:3)
您没有正确阅读错误。它告诉您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
对象传递给其他线程),则应std::move
你的port
对象进入主题:
std::thread s( serial_read<boost::asio::serial_port>, std::move(port) );
这还需要将serial_read
的定义更改为按值Port
:
template <typename Port>
void serial_read( Port port) {}
答案 1 :(得分:2)
简单修复(我相信,未经测试)是使用引用包装器(如果你真的需要在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)) );
在 bound 对象中,存储每个参数的副本,这要求参数可以复制构造。使用引用包装器允许复制(复制包装器,原始对象不复制)。
另一种替代方法是,如果您不需要在port
中保持main
对象有效,则可以从中移除,以便复制而不是 >绑定对象,允许实现从main
中的对象移动。