如果我們有一個H多載operator()的類。如何在不從 class 實體化物件的情況下從這些成員函式創建執行緒H。考慮以下代碼
#include<iostream>
#include<thread>
class H {
public:
void operator()(){
printf("This is H(), I take no argument\n");
}
void operator()(int x){
printf("This is H(), I received %d \n",x);
}
};
int main(){
int param = 0xD;
//No object created
std::thread td_1 = std::thread(H());
std::thread td_2 = std::thread(H(),param);
td_1.join();
td_2.join();
//From an object
H h;
std::thread td_3 = std::thread(h);
std::thread td_4 = std::thread(h,param);
td_3.join();
td_4.join();
return 0;
}
產生輸出:
This is H(), I take no argument
This is H(), I received 13
This is H(), I take no argument
This is H(), I received 13
問題是, td_1 和 td_2 如何在沒有 class 物件的情況下呼叫operator()class的成員函式?HH
uj5u.com熱心網友回復:
td_1 和 td_2 如何在沒有 H 類物件的情況下呼叫 H 類的成員函式 operator()?
td_1并td_2創建型別的物件H。這些物件是臨時的。接下來,那些提供的函式物件(在這種情況下是臨時的)被移動/復制到屬于新創建的執行執行緒的存盤中并從那里呼叫。
您可以通過添加默認建構式并在類中移動建構式來確認這一點,H如下所示:
#include<iostream>
#include<thread>
class H {
public:
void operator()(){
printf("This is H(), I take no argument\n");
}
void operator()(int x){
printf("This is H(), I received %d \n",x);
}
//default constructor
H()
{
std::cout<<"default constructor called"<<std::endl;
}
//move constructor
H(H&&)
{
std::cout<<"move constructor called"<<std::endl;
}
};
int main(){
int param = 0xD;
std::thread td_1 = std::thread(H());
std::thread td_2 = std::thread(H(),param);
td_1.join();
td_2.join();
return 0;
}
上述程式的輸出是:
default constructor called
move constructor called
move constructor called
default constructor called
move constructor called
move constructor called
This is H(), I take no argument
This is H(), I received 13
uj5u.com熱心網友回復:
考慮這個函式:
void f() {
printf("This is f(), I take no argument\n");
}
呼叫該函式的執行緒的構造類似于std::thread(f). 類似的代碼std::thread(f())是無效的,因為 的引數std::thread必須是可呼叫的(在這種情況下,是一個函式物件)。如果在將函式傳遞給建構式之前呼叫該函式,std::thread則不能再呼叫它。
所以你傳遞f給建構式,它后來變成f()了,函式被呼叫。
與傳遞函式名類似,可以將物件傳遞給建構式,執行緒稍后呼叫operator(). 當你寫的時候std::thread(H()),你構造了一個臨時物件。因為 class Hhas operator(),所以接受此代碼。
其實std::thread(H{})也是可以接受的。這表明括號是指建構式H::H(),而不是H::operator()。您沒有為該類撰寫建構式,但編譯器創建了一個默認建構式。
您還可以使用此代碼構造一個臨時物件H()并立即呼叫operator():
int main() {
H()(); // Valid: H() is callable
//f()(); // Invalid: f() is not callable
}
uj5u.com熱心網友回復:
語法是在此背景關系中H()創建型別的臨時物件。H臨時物件被傳遞給std::thread建構式。
現在,如果執行緒要呼叫operator()該臨時檔案,那將是一個問題,因為臨時檔案將只存在到行尾,std::thread td_1 = std::thread(H());并且執行緒函式可能會在那之后執行。
但是,執行緒實際上并沒有使用那個臨時的。相反,為執行緒創建了一個(衰減的)引數型別的新物件,從您提供給建構式的臨時物件中復制/移動。這個H物件一直存在,直到執行緒退出并在這個物件operator()上被呼叫。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/430571.html
