C++拾遺--lambda表達式原理
來源:程序員人生 發布時間:2015-03-30 08:18:17 閱讀次數:2829次
C++拾遺--lambda表達式原理
前言
lambda表達式是在C++11新標準中提出的。在lambda表達式中,我們集中梳理了1下它的使用。現在來討論下它的實現原理。
正文
1.函數對象
類的對象跟括號結合,表現出函數1般的行動,這個對象可以稱作是函數對象。
#include <iostream>
using namespace std;
class MyClass
{
public:
//重載函數調用運算符()
int operator()(int i)
{
return i;
}
};
int main()
{
MyClass my;
//my()的調用行動似同函數
int i = my(1); //本質是調用 my.operator()(1)
cout << "i = " << i << endl;
cin.get();
return 0;
}
運行

這個示例說明函數對象的本質是重載了函數調用運算符。當1個類重載了函數調用運算符()后,它的對象就成了函數對象。這是理解lambda表達式內部實現的基礎。
2.lambda表達式原理
原理:編譯器會把1個lambda表達式生成1個匿名類的匿名對象,并在類中重載函數調用運算符。
我們從最簡單的lambda表達式入手,從易到難
2.1 無捕獲列表和參數列表
auto print = []{cout << "zhangxiang" << endl; };
編譯器會把這1句翻譯成以下情形:
//用給定的lambda表達式生成相應的類
class print_class
{
public:
void operator()(void) const
{
cout << "zhangxiang" << endl;
}
};
//用構造的類創建對象,print此時就是1個函數對象
auto print = print_class();
生成類的類名命名規則可以多變,不1定非得這樣。
2.2 無捕獲列表但有參數列表
auto add = [](int a, int b){return a + b; };
編譯器會把這1句翻譯成以下情形:
class add_class
{
public:
auto operator()(int a, int b) const
{
return a + b;
}
};
auto add = add_class();
2.3 有捕獲列表,參數列表可選
由于捕獲方式分為兩種:援用捕獲、值捕獲,故此種情況下,又可細分。
2.3.1 值捕獲
int year = 19900212;
char *name = "zhangxiang";
//采取值捕獲,捕獲所有的已定義的局部變量,如year,name
auto print = [=](){
cout << year << ends << name << endl;
};
翻譯
int year = 19900212;
char *name = "zhangxiang";
class print_class
{
public:
//根據捕獲列表來決定構造函數的參數列表情勢
print_class(int year, char *name) :year(year), name(name)
{
}
void operator()(void) const
{
cout << year << ends << name << endl;
}
private:
int year;
char *name;
};
auto print = print_class(a, str);
運行效果是1樣的,就不演示了。
2.3.2 援用捕獲
int year = 19900212;
char *name = "zhangxiang";
auto print = [&](){
year++;
cout << year << ends << name << endl;
};
翻譯
int year = 19900212;
char *name = "zhangxiang";
class print_class
{
public:
//由因而援用捕獲,參數列表采取援用的方式
print_class(int &year, char *&name) :year(year), name(name)
{
}
void operator()(void) const
{
year++; //編譯通過,const對援用類型無效
cout << year << ends << name << endl;
}
private:
int &year;
char *&name;
};
經過測試,效果也是1樣的。
2.3.3 混合捕獲
int year = 19900212;
int shoes = 42;
char *name = "zhangxiang";
auto show = [&, shoes]()mutable{
shoes++;
year++;
cout << year << ends << shoes << ends << name << endl;
};
翻譯
int year = 19900212;
int shoes = 42;
char *name = "zhangxiang";
class show_class
{
private:
int &year;
mutable int shoes;
char *&name;
public:
show_class(int &year, int shoes, char *&name) :year(year), shoes(shoes), name(name)
{
}
void operator()(void)const
{
shoes++;
year++;
cout << year << ends << shoes << ends << name << endl;
}
};
auto show = show_class(year, shoes, name);
show();
默許情況下,經過值捕獲的變量是不可以被修改的,除非在參數列表后加關鍵字mutable。以上代碼展現了,對應類中mutable是如何加的。固然還有另外一種實現方法,只要lambda表達式加了mutable,重載函數調用運算符時就不加const修飾。
總結
以上這些示例代碼基本上把各種情形的lambda表達式的實現原理都展現出來了,仔細想一想還是挺容易的。
本專欄目錄
所有內容的目錄
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈