C++11/14 線程調(diào)用類對象和線程傳參的方法
線程調(diào)用類對象
在前面的示例中,我們?yōu)榫€程任務(wù)使用了通常的函數(shù)。實際上,我們可以使用任何可調(diào)用對象或者lambda函數(shù),如下調(diào)用類對象的例子:
#include <iostream> #include <thread> class MyFunctor { public: void operator()() { std::cout << "functor\n"; } }; int main() { MyFunctor fnctor; std::thread t(fnctor); std::cout << "main thread\n"; t.join(); return 0; }
在這里,我們創(chuàng)建了一個函數(shù)對象,并將其分配給線程任務(wù),我們可能會用這種方法嘗試此實例:
// MyFunctor fnctor; std::thread t(MyFunctor());
但是編譯不通過,所以,如果我們想讓它工作,我們應(yīng)該這樣做:
// MyFunctor fnctor; std::thread t((MyFunctor()));
就是說我們必須添加 ()包含 MyFunctor().
為什么?我這邊不去深究,它跟C++函數(shù)聲明規(guī)定相關(guān)。
線程傳參
下面是將參數(shù)傳遞給線程的示例。 在這個例子中,我們傳遞一個字符串:
#include <iostream> #include <thread> #include <string> void thread_function(std::string s) { std::cout << "thread function "; std::cout << "message is = " << s << std::endl; } int main() { std::string s = "Kathy Perry"; std::thread t(&thread_function, s); std::cout << "main thread message = " << s << std::endl; t.join(); return 0; }
從下面的輸出中,我們知道字符串已經(jīng)成功地傳遞給了線程函數(shù)。
thread function message is = Kathy Perry main thread message = Kathy Perry
如果我們想以引用方式傳遞,我們可能會這樣做:
void thread_function(std::string &s) { std::cout << "thread function "; std::cout << "message is = " << s << std::endl; s = "Justin Beaver"; }
為確保字符串真的是以引用方式傳遞,我們在線程函數(shù)尾部修改了字符串的內(nèi)容。但是輸出并沒有改變:
thread function message is = Kathy Perry main thread message = Kathy Perry
實際上,字符串是以值傳遞的而不是引用傳遞。為了以引用方式傳遞,我們應(yīng)該使用std::ref稍微修改下代碼:
std::thread t(&thread;_function, std::ref(s));
然后,修改后的輸出為:
thread function message is = Kathy Perry main thread message = Justin Beaver
有另一種免復(fù)制、非內(nèi)存共享的方法在線程間傳遞參數(shù)。 我們可以使用 move():
std::thread t(&thread_function, std::move(s));
當(dāng)字符串被從main函數(shù)移動到線程函數(shù)后,main函數(shù)就不再有這個變量了,輸出為空值:
thread function message is = Kathy Perry main thread message =
線程復(fù)制和移動 copy / move
如下代碼期望拷貝線程是編譯不通過的:
#include <iostream> #include <thread> void thread_function() { std::cout << "thread function\n"; } int main() { std::thread t(&thread;_function); std::cout << "main thread\n"; std::thread t2 = t; t2.join(); return 0; }
但是我們可以通過move把其所有權(quán)轉(zhuǎn)移,見如下代碼:
// t5.cpp #include <iostream> #include <thread> void thread_function() { std::cout << "thread function\n"; } int main() { std::thread t(&thread;_function); std::cout << "main thread\n"; std::thread t2 = move(t); t2.join(); return 0; }
程序輸出:
$ g++ t5.cpp -o t5 -std=c++11 -pthread
$ ./t5
main thread
thread function
線程ID
我們可以通過 this_thread::get_id()獲取線程的id信息:
int main() { std::string s = "Kathy Perry"; std::thread t(&thread_function, std::move(s)); std::cout << "main thread message = " << s << std::endl; std::cout << "main thread id = " << std::this_thread::get_id() << std::endl; std::cout << "child thread id = " << t.get_id() << std::endl; t.join(); return 0; }
輸出:
thread function message is = Kathy Perry
main thread message =
main thread id = 1208
child thread id = 5224
創(chuàng)建多少線程呢?
線程庫提供了線程數(shù)量的建議函數(shù)hardware_concurrency():
int main() { std::cout << "Number of threads = " << std::thread::hardware_concurrency() << std::endl; return 0; }
輸出:
Number of threads = 2
Lambda函數(shù)
既然我們談的C++,那么讓我們來了解下Lambda。
我們可以用lambda函數(shù)(匿名函數(shù))這樣替換線程函數(shù):
int main() { std::thread t([]() { std::cout << "thread function\n"; } ); std::cout << "main thread\n"; t.join(); // main thread waits for t to finish return 0; }
注意,我們正在編寫內(nèi)聯(lián)代碼,并將其傳遞到另一個線程構(gòu)造函數(shù)中。
Lambda表達(dá)式是用括號括起來的一系列語句, 前綴用[], 調(diào)用lambda編譯接口告訴編譯器我們正在聲明一個lambda函數(shù), 在我們的例子中,沒有傳遞參數(shù)。我們本質(zhì)上可以用 {} 作為一個任務(wù) , 并把它分配給我們的線程。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
c++實現(xiàn)單純形法現(xiàn)行規(guī)劃問題的求解(推薦)
這篇文章主要介紹了c++實現(xiàn)單純形法現(xiàn)行規(guī)劃問題的求解,本文針對問題通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04C語言二叉樹常見操作詳解【前序,中序,后序,層次遍歷及非遞歸查找,統(tǒng)計個數(shù),比較,求深度】
這篇文章主要介紹了C語言二叉樹常見操作,結(jié)合實例形式詳細(xì)分析了基于C語言的二叉樹前序,中序,后序,層次遍歷及非遞歸查找,統(tǒng)計個數(shù),比較,求深度等相關(guān)操作技巧與注意事項,需要的朋友可以參考下2018-04-04C++?Cartographer源碼中關(guān)于傳感器的數(shù)據(jù)傳遞實現(xiàn)
這篇文章主要介紹了C++?Cartographer源碼中關(guān)于傳感器的數(shù)據(jù)傳遞實現(xiàn),前面已經(jīng)談到了Cartographer中添加軌跡的方法和傳感器的數(shù)據(jù)流動走向。發(fā)現(xiàn)在此調(diào)用了LaunchSubscribers這個函數(shù)來訂閱相關(guān)傳感器數(shù)據(jù)2023-03-03