您好,登錄后才能下訂單哦!
今天小編給大家分享一下C++中l(wèi)ambda和function如何使用的相關(guān)知識點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
lambda表達(dá)式又稱為匿名表達(dá)式,是C11提出的新語法。[]存儲lambda表達(dá)式要捕獲的值,()內(nèi)的參數(shù)為形參,可供外部調(diào)用傳值。lambda表達(dá)式可以直接調(diào)用
// 1 匿名調(diào)用 [](string name) { cout << "this is anonymous" << endl; cout << "hello " << name << endl; }("zack");
上述代碼定義了一個匿名函數(shù)后直接調(diào)用。我們可以通過auto初始化一個變量存儲lambda表達(dá)式
// 2 通過auto賦值 auto fname = [](string name) { cout << "this is auto " << endl; cout << "hello " << name << endl; }; fname("Rolin");
通過auto定義fname,然后存儲了lambda表達(dá)式,之后調(diào)用fname即可。也可以通過函數(shù)指針的方式接受lambda表達(dá)式
typedef void (*P_NameFunc)(string name); // 3 函數(shù)指針 P_NameFunc fname2 = [](string name) { cout << "this is P_NameFunc " << endl; cout << "hello " << name << endl; }; fname2("Vivo");
P_NameFunc定義了fname2函數(shù)指針接受了lambda表達(dá)式。也可以通過function對象接受lambda表達(dá)式,function類是C11新增的語法。
// 4 function function<void(string)> funcName; funcName = [](string name) { cout << "this is function " << endl; cout << "hello " << name << endl; }; funcName("Uncle Wang");
用一個function對象接受了lambda表達(dá)式,同樣可以調(diào)用該function對象funcName達(dá)到調(diào)用lambda的效果。
1 值捕獲
int age = 33; string name = "zack"; int score = 100; string job = "softengineer"; //值捕獲 [age, name](string name_) { cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl; }("Novia");
上述lambda表達(dá)式捕獲了age和name,是以值的方式來捕獲的。所以無法在lambda表達(dá)式內(nèi)部修改age和name的值,如果修改age和name,編譯器會報錯,提示無法修改const常量,因為age和name是以值的方式被捕獲的。
2 引用捕獲
int age = 33; string name = "zack"; int score = 100; string job = "softengineer"; [&age, &name](string name_) { cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl; name = "Xiao Li"; age = 18; }("Novia");
[]里age和name前邊添加了&,此時age和name是以引用方式捕獲的。所以可以在lambda表達(dá)式中修改age和name的值。
C++的lambda表達(dá)式雖然可以捕獲局部變量的引用,達(dá)到類似閉包的效果,但不是真的閉包,golang和python等語言通過閉包捕獲局部變量后可以增加局部變量的聲明周期,C++無法做到這一點(diǎn),所以下面的調(diào)用會出現(xiàn)崩潰。
vector<function<void(string)>> vec_Funcs; void use_lambda2() { int age = 33; string name = "zack"; int score = 100; string job = "softengineer"; vec_Funcs.push_back([age, name](string name_) { cout << "this is value catch " << endl; cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl; }); //危險,不要捕獲局部變量的引用 vec_Funcs.push_back([&age, &name](string name_) { cout << "this is referenc catch" << endl; cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl; }); } void use_lambda3() { for (auto f : vec_Funcs) { f("zack"); } } int main(){ use_lambda2(); use_lambda3(); }
use_lambda2中將lambda表達(dá)式存儲在function類型的vector里,當(dāng)use_lambda2結(jié)束后,里邊的局部變量都被釋放了,而vector中的lambda表達(dá)式還存儲著局部變量的引用,在調(diào)用use_lambda3時調(diào)用lambda表達(dá)式,此時訪問局部變量已經(jīng)被釋放了,所以導(dǎo)致程序崩潰。
3 全部用值捕獲,name用引用捕獲
int age = 33; string name = "zack"; int score = 100; string job = "softengineer"; [=, &name]() { cout << "age is " << age << " name is " << name << " score is " << score << " job is " << job << endl; name = "Cui Hua"; }();
通過=表示所有變量都以值的方式捕獲,如果希望某個變量以引用方式捕獲則單獨(dú)在這個變量前加&。
4 全部用引用捕獲,只有name用值捕獲
int age = 33; string name = "zack"; int score = 100; string job = "softengineer"; [&, name]() { cout << "age is " << age << " name is " << name << " score is " << score << " job is " << job << endl; }();
通過&方式表示所有變量都已引用方式捕獲,如果希望某個變量以值方式捕獲則單獨(dú)在這個變量前加=。
我們可以用function存儲形參和返回值相同的一類函數(shù)指針,可調(diào)用對象,lambda表達(dá)式等。
void use_function() { list<function<void(string)>> list_Funcs; //存儲函數(shù)對象 list_Funcs.push_back(FuncObj()); //存儲lambda表達(dá)式 list_Funcs.push_back([](string str) { cout << "this is lambda call " << str << endl; }); //存儲全局函數(shù) list_Funcs.push_back(globalFun); for (const auto &f : list_Funcs) { f("hello zack"); } }
C11同樣提供了bind操作,將原函數(shù)的幾個參數(shù)通過bind綁定傳值,返回一個新的可調(diào)用對象。
//綁定全局函數(shù) auto newfun1 = bind(globalFun2, placeholders::_1, placeholders::_2, 98, "worker"); //相當(dāng)于調(diào)用globalFun2("Lily",22, 98,"worker"); newfun1("Lily", 22); //多傳參數(shù)沒有用,相當(dāng)于調(diào)用globalFun2("Lucy",28, 98,"worker"); newfun1("Lucy", 28, 100, "doctor"); auto newfun2 = bind(globalFun2, "zack", placeholders::_1, 100, placeholders::_2); //相當(dāng)于調(diào)用globalFun2("zack",33,100,"engineer"); newfun2(33, "engineer"); auto newfun3 = bind(globalFun2, "zack", placeholders::_2, 100, placeholders::_1); newfun3("coder", 33);
placeholders表示占位符,_1表示新生成函數(shù)的第一個參數(shù), _2表示新生成函數(shù)的第二個參數(shù),將這些參數(shù)傳遞給原函數(shù)達(dá)到占位的效果,原函數(shù)的其余參數(shù)通過bind綁定固定值。
接下來定義類
class BindTestClass { public: BindTestClass(int num_, string name_) : num(num_), name(name_) {} static void StaticFun(const string &str, int age); void MemberFun(const string &job, int score); public: int num; string name; };
實現(xiàn)靜態(tài)函數(shù)和成員函數(shù)
void BindTestClass::StaticFun(const string &str, int age) { cout << "this is static function" << endl; cout << "name is " << str << endl; cout << "age is " << age << endl; } void BindTestClass::MemberFun(const string &job, int score) { cout << "this is member function" << endl; cout << "name is " << name << endl; cout << "age is " << num << endl; cout << "job is " << job << endl; cout << "score is " << score << endl; }
我們通過bind綁定靜態(tài)成員函數(shù)
//綁定類的靜態(tài)成員函數(shù),加不加&都可以 // auto staticbind = bind(BindTestClass::StaticFun, placeholders::_1, 33); auto staticbind = bind(&BindTestClass::StaticFun, placeholders::_1, 33); staticbind("zack");
新生成的staticbind函數(shù)可以直接傳遞一個參數(shù)zack就完成了調(diào)用。接下來用bind綁定成員函數(shù)
BindTestClass bindTestClass(33, "zack"); // 綁定類的成員函數(shù),一定要傳遞對象給bind的第二個參數(shù),可以是類對象,也可以是類對象的指針 // 如果要修改類成員,必須傳遞類對象的指針 auto memberbind = bind(BindTestClass::MemberFun, &bindTestClass, placeholders::_1, placeholders::_2); memberbind("coder", 100); auto memberbind2 = bind(BindTestClass::MemberFun, placeholders::_3, placeholders::_1, placeholders::_2); memberbind2("coder", 100, &bindTestClass); //綁定類成員時,對象必須取地址 auto numbind = bind(&BindTestClass::num, placeholders::_1); std::cout << numbind(bindTestClass) << endl;
當(dāng)然也可以直接用function對象接受bind返回的結(jié)果
// function接受bind返回的函數(shù) function<void(int, string)> funcbind = bind(globalFun2, "zack", placeholders::_1, 100, placeholders::_2); funcbind(33, "engineer"); // function接受bind 成員函數(shù) function<void(string, int)> funcbind2 = bind(BindTestClass::MemberFun, &bindTestClass, placeholders::_1, placeholders::_2); funcbind2("docker", 100); function<void(string, int, BindTestClass *)> funcbind3 = bind(BindTestClass::MemberFun, placeholders::_3, placeholders::_1, placeholders::_2); funcbind3("driver", 100, &bindTestClass); // function 直接接受成員函數(shù),function的模板列表里第一個參數(shù)是類對象引用 function<void(BindTestClass &, const string &, int)> functomem = BindTestClass::MemberFun; functomem(bindTestClass, "functomem", 88); // function 綁定類的靜態(tài)成員函數(shù) function<void(const string &)> funbindstatic = bind(&BindTestClass::StaticFun, placeholders::_1, 33); funbindstatic("Rolis");
以上就是“C++中l(wèi)ambda和function如何使用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。