标签:lambda表达式原理 函数对象 值捕获 引用捕获 lambda
C++拾遗--lambda表达式原理
lambda表达式是在C++11新标准中提出的。在lambda表达式中,我们集中梳理了一下它的使用。现在来讨论下它的实现原理。
类的对象跟括号结合,表现出函数一般的行为,这个对象可以称作是函数对象。
#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; }运行
这个示例说明函数对象的本质是重载了函数调用运算符。当一个类重载了函数调用运算符()后,它的对象就成了函数对象。这是理解lambda表达式内部实现的基础。
原理:编译器会把一个lambda表达式生成一个匿名类的匿名对象,并在类中重载函数调用运算符。
我们从最简单的lambda表达式入手,从易到难
auto print = []{cout << "zhangxiang" << endl; };编译器会把这一句翻译成如下情形:
//用给定的lambda表达式生成相应的类 class print_class { public: void operator()(void) const { cout << "zhangxiang" << endl; } }; //用构造的类创建对象,print此时就是一个函数对象 auto print = print_class();生成类的类名命名规则可以多变,不一定非得这样。
auto add = [](int a, int b){return a + b; };编译器会把这一句翻译成如下情形:
class add_class { public: auto operator()(int a, int b) const { return a + b; } }; auto add = add_class();
由于捕获方式分为两种:引用捕获、值捕获,故此种情况下,又可细分。
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);运行效果是一样的,就不演示了。
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; };经过测试,效果也是一样的。
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();
以上这些示例代码基本上把各种情形的lambda表达式的实现原理都展现出来了,仔细想想还是挺容易的。
本专栏目录
标签:lambda表达式原理 函数对象 值捕获 引用捕获 lambda
原文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/44064765