2013-03-27 70 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