2013-03-27 68 views
1

我正尝试创建一个在专用线程中运行的函数,其中 从串口读取。但我无法将连接 传递给线程。我在我的代码减少到下面的例子:由于移动构造函数而被删除的对象

#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 

错误消息是很清楚。我试图使用一个对象 ,该对象由于移动构造函数声明 而被删除,因此该对象不存在。但我仍然不明白 这里发生了什么,以及如何正确地做到这一点。有人可以给我 吗?

+2

错误消息不会说出你认为它的意思。这是说复制构造函数已被标记为_deleted_,即没有复制构造函数。该对象本身被_not_删除。 – 2013-03-27 14:55:15

回答

3

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

如果你真的需要一个参考传递给serial_read,你需要换你port对象在reference_wrapper

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

但是,如果你不保持的port和使用保持它为别的(如传球同样port对象给其他线程),你应该std::moveport对象插入线程:

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

钍被要求也在改变serial_read定义中值取Port

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

这引发了一个不同的错误:错误:类型为'boost :: asio :: basic_serial_port <>'的类型为'boost :: asio :: basic_serial_port <>&'的非const引用无效初始化 – Marco 2013-03-27 15:01:26

+0

@ Marco:问题是你是否需要这个函数来接收对象的*引用*或者它可以获得它自己的。如果你需要一个引用,你必须使用一个引用包装器,如果它可以使用它自己的(你不关心'main'中的'port'发生了什么),那么改变'serial_read'的签名来接受参数值。 (未经测试,里程*将*有所不同) – 2013-03-27 15:04:01

+0

我不需要''main',但我需要它在其他线程。 – Marco 2013-03-27 15:05:37

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))); 

绑定对象的参数每一个的副本被存储,这需要的参数被拷贝构造。引用包装的使用允许复制(包装被复制,原始对象不被复制)。

另一种选择,如果你不需要保持port对象main有效的是从它移动,以便不用复制势必对象允许您从实施到移动对象在main

+0

我认为我们的两种解决方案都可行。一个是参考,一个不是。 – 2013-03-27 14:59:45

+0

此解决方案似乎工作。我会检查它是否可以作为更大项目的一部分。 – Marco 2013-03-27 15:03:53