C++ Thread類報錯
阿新 • • 發佈:2019-01-30
#include <thread>
#include <iostream>
void start_thread(int& param) {
std::cout << param << std::endl;
}
int main() {
int value(7);
std::thread mythread(start_thread, value);
mythread.join();
return 0;
}
乍看之下,有一個“引用包裝器”,而不是一個普通的舊引用似乎沒有什麼用處。它的直接用處被這樣一個事實所掩蓋:它只有在使用像C ++ 11一樣新增的其他新特性(如 std::bind
和std::thread
)時才真正有用。std::ref
是一種解決方法,用於模板型別推導規則推導引數型別的情況,以便引數按值取值,而意圖是通過引用來取引數。
報錯資訊類似:
In file included from /usr/include/c++/5.3.0/thread:39:0, from main.cpp:1: /usr/include/c++/5.3.0/functional: In instantiation of ‘struct std::_Bind_simple<void (*(int))(int&)>’: /usr/include/c++/5.3.0/thread:137:59: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(int&); _Args = {int&}]’ main.cpp:11:45: required from here /usr/include/c++/5.3.0/functional:1505:61: error: no type named ‘type’ in ‘class std::result_of<void (*(int))(int&)>’ typedef typename result_of<_Callable(_Args...)>::type result_type; ^ /usr/include/c++/5.3.0/functional:1526:9: error: no type named ‘type’ in ‘class std::result_of<void (*(int))(int&)>’ _M_invoke(_Index_tuple<_Indices...>) ^
忽略這裡明顯的設計缺陷;這個例子只是為了演示當你嘗試傳遞一個值引數時引用從std::thread::thread()
等模板函式呼叫的函式時會發生什麼。請注意,模板型別推導(正確)推導值的型別為int
,但這不符合它在start_thread中看到的int&
型別。編譯器給出的實際錯誤(在這種情況下為GCC)實際上比這更為模糊:
編譯器確實表明,錯誤隱約與將函式引數繫結到傳入的函式有關; 使用指向std::ref
的錯誤中的關鍵字作為解決方案進行線上快速搜尋。
那麼std::ref
如何通過引用將引數傳遞給引數型別按值推導的模板函式?std::reference_wrapper
(由std::ref
返回的型別)及其libstdc ++ 文件 / 原始碼的定義描繪了一幅非常清晰的圖片。 std::reference_wrapper
只是一個隱式地轉換為引用的指標的薄包裝(通過operator T&() const
):
所以模板函式中引數的推導型別是std::reference_wrapper<T>
(在上面的例子中是std::reference_wrapper<int>
),它可以通過值傳遞給函式。這與參考大小相同,當它傳遞給另一個需要引數的函式時,它會隱式轉換為一個引數。所以在功能上,它聞起來很像一個參考。讓我們看看它的行動:
#include <thread>
#include <iostream>
#include <functional>
void start_thread(int& param) {
std::cout << param << std::endl;
}
int main() {
int value(7);
std::thread mythread(start_thread, std::ref(value));
mythread.join();
return 0;
}
output:7