我是靠谱客的博主 粗心黄蜂,最近开发中收集的这篇文章主要介绍C++拾遗--lambda表达式原理前言正文,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

                      C++拾遗--lambda表达式原理

前言

    lambda表达式是在C++11新标准中提出的。在lambda表达式中,我们集中梳理了一下它的使用。现在来讨论下它的实现原理。

正文

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;
}
运行



这个示例说明函数对象的本质是重载了函数调用运算符。当一个类重载了函数调用运算符()后,它的对象就成了函数对象。这是理解lambda表达式内部实现的基础。


2.lambda表达式原理

原理:编译器会把一个lambda表达式生成一个匿名类的匿名对象,并在类中重载函数调用运算符。

我们从最简单的lambda表达式入手,从易到难

2.1 无捕获列表和参数列表

auto print = []{cout << "zhangxiang" << endl; };
编译器会把这一句翻译成如下情形:

//用给定的lambda表达式生成相应的类
class print_class
{
public:
void operator()(void) const
{
cout << "zhangxiang" << endl;
}
};
//用构造的类创建对象,print此时就是一个函数对象
auto print = print_class();
生成类的类名命名规则可以多变,不一定非得这样。


2.2 无捕获列表但有参数列表

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();


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);
运行效果是一样的,就不演示了。


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;
};
经过测试,效果也是一样的。

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表达式的实现原理都展现出来了,仔细想想还是挺容易的。



本专栏目录

  • C++拾遗 目录
所有内容的目录
  • CCPP Blog 目录

最后

以上就是粗心黄蜂为你收集整理的C++拾遗--lambda表达式原理前言正文的全部内容,希望文章能够帮你解决C++拾遗--lambda表达式原理前言正文所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部