C++ Lambda表达式

C++ Lambda表达式(匿名函数)
[capture list] (parameters) mutable throw() ->return-type {statement}
[捕获列表](参数列表)可变规则 返回类型{函数体}

一、捕获列表:

在C++规范中也称为Lambda导入器,捕获列表总是出现在Lambda函数的开始处。实际上,[]是Lambda引出符。编译器根据该引出符判断接下来的代码是否是Lambda函数,捕获列表能够捕捉上下文中的变量以供Lambda函数使用。

[] 表示不捕获任何变量
[var] 表示值传递方式捕获变量var
[=] 表示值传递方式捕获所有父作用域的变量(包括this)
[&var] 表示引用传递捕捉变量var
[&] 表示引用传递方式捕捉所有父作用域的变量(包括this)
[this] 表示值传递方式捕捉当前的this指针
[=, &] 拷贝与引用混合
[=, &a, &b] 表示以引用传递的方式捕捉变量a和b,以值传递方式捕捉其它所有变量。
[&, a, this] 表示以值传递的方式捕捉变量a和this,引用传递方式捕捉其它所有变量。
不过值得注意的是,捕捉列表不允许变量重复传递。下面例子就是典型的重复,会导致编译时期的错误。例如:
[=,a]这里已经以值传递方式捕捉了所有变量,但是重复捕捉a了,会报错的;
[&,&this]这里&已经以引用传递方式捕捉了所有变量,再捕捉this也是一种重复。

二、参数列表:

参数列表是可选的,并且在大多数方面类似于函数的参数列表。如果不需要参数传递,则可以连同括号“()”一起省略。

例如:

```cpp
auto function = [] (int first, int second){
    return first + second;
};
	
function(100, 200);

三、可变规格mutable:

mutable修饰符, 默认情况下Lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空)。
例如:

int m = 0;
int n = 0;
[&, n] (int a) mutable { m = ++n + a; }(4);
cout << m << endl << n << endl;

四、异常说明:

用于Lamdba表达式内部函数抛出异常。使用 throw() 异常规范来指示 Lambda 表达式不会引发任何异常。与普通函数一样,如果 Lambda 表达式声明 C4297 异常规范且 Lambda 体引发异常,Visual C++ 编译器将生成警告 throw() 。

int main() // C4297 expected 
{ 
 	[]() throw() { throw 5; }(); 
}

五、返回类型:

追踪返回类型形式声明函数的返回类型。我们可以在不需要返回值的时候也可以连同符号”->”一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导。
1、Lambda表达式的返回类型会自动推导。
2、除非你指定了返回类型,否则不必使用关键字。
3、返回型类似于通常的方法或函数的返回型部分。
4、返回类型必须在参数列表之后,并且必须在返回类型->之前包含类型关键字。
5、如果Lambda主体仅包含一个return语句或该表达式未返回值,则可以省略Lambda表达式的return-type部分。
6、如果Lambda主体包含一个return语句,则编译器将从return表达式的类型中推断出return类型。
否则,编译器将返回类型推导为void

六、lambda函数体:

内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。

七、lambda表达式的优缺点

优点:

1、可以在需要调用的函数的位置定义短小精悍的函数,不需要提前预定义
2、lamdba表达式变得更加紧促,结构层次更加明显,代码可读性好

缺点:

1、因其使用灵活性,增加了代码阅读难度。
2、对于函数复用无能为力

八、lambda表达式的工作原理

编译器会把一个Lambda表达式生成一个匿名类的匿名对象,并在类中重载函数调用运算符,实现了一个operator()方法。

auto print = []{cout << "Hello!" << endl; };

编译器会把上面这一句翻译为下面的代码:

class print_class
{
public:
	void operator()(void) const
	{
		cout << "Hello!" << endl;
	}
};

// 用构造的类创建对象,print此时就是一个函数对象

auto print = print_class();

九、C++仿函数

仿函数(functor)又称为函数对象(function object)是一个能行使函数功能的类。仿函数的语法几乎和我们普通的函数调用一样,不过作为仿函数的类,都必须重载operator()运算符,仿函数与Lamdba表达式的作用是一致的。举例:

#include 
#include 
using namespace std;
 
class Functor
{
public:
    void operator() (const string& str) const
    {
        cout << str << endl;
    }
};
 
int main()
{
    Functor myFunctor;
    myFunctor("Hello world!");
    return 0;
}

你可能感兴趣的:(c++,开发语言)