C++11新特性学习笔记(二)

C++11引入了lambda(匿名函数),这样就可以在一个函数只需调用一次的地方使用了,类似内联函数。

C++11 的 lambda 表达式规范如下:

[ capture ] ( params ) mutable exception attribute -> ret { body } (1)
[ capture ] ( params ) -> ret { body } (2)
[ capture ] ( params ) { body } (3)
[ capture ] { body } (4)

其中

  • (1) 是完整的 lambda 表达式形式,
  • (2) const 类型的 lambda 表达式,该类型的表达式不能改捕获("capture")列表中的值。
  • (3)省略了返回值类型的 lambda 表达式,但是该 lambda 表达式的返回类型可以按照下列规则推演出来:
    • 如果 lambda 代码块中包含了 return 语句,则该 lambda 表达式的返回类型由 return 语句的返回类型确定。
    • 如果没有 return 语句,则类似 void f(...) 函数。
  • 省略了参数列表,类似于无参函数 f()。

mutable 修饰符说明 lambda 表达式体内的代码可以修改被捕获的变量,并且可以访问被捕获对象的 non-const 方法。

exception 说明 lambda 表达式是否抛出异常(noexcept),以及抛出何种异常,类似于void f() throw(X, Y)

attribute 用来声明属性。

另外,capture 指定了在可见域范围内 lambda 表达式的代码内可见得外部变量的列表,具体解释如下:

  • [a,&b] a变量以值的方式呗捕获,b以引用的方式被捕获。
  • [this] 以值的方式捕获 this 指针。
  • [&] 以引用的方式捕获所有的外部自动变量。
  • [=] 以值的方式捕获所有的外部自动变量。
  • [] 不捕获外部的任何变量。

此外,params 指定 lambda 表达式的参数。

举个例子:

#include <iostream>
using namespace std;


int main()
{
int id = 83;
auto e = [id](){
static int count = 1;
cout << "id_e"<<count++<<":" << id << endl;
//++id; //id为传值方式传入,无权修改id的值
};
auto f = [id]()mutable{
static int count = 1;
cout << "id_f"<< count++ << ":" << id << endl;
++id; //id为传值的方式传入,可以修改id的值,但是该id只作为该匿名函数的私有对象,不是外部捕获变量
};


auto g = [&id](){
static int count = 1;
cout << "id_g" << count++ << ":" << id << endl;
++id; //id为传引用的方式,函数可以任意修改外部捕获的值,因为此id和外部id是相同变量(具有相同地址)
};


auto h = [&id]()mutable{
static int count = 1;
cout << "id_h" << count++ << ":" << id << endl;
++id; //同函数g
};
id = 42;
e();
f();
f();
g();
h();
id = 89;
e();
f();
g();
h();
cout << "final id=" << id << endl;


return 0;
}


运行结果:


可以看到函数e中的id一直没有变化,都是初始值83。注意:捕获值是捕获函数声明前最近的变量的值,即所有以匿名函数捕获的都是最开始的id,但是由于对id的传入方式不一样导致结果不一样!

函数f的值是根据初始的83变化的,并不跟随外部id的改变而改变。

函数g和函数h则是根据外部id值的变化进行改变。


综上所述可以将上述lambda的行为视为一个函数对象(类),如下:

class 
{
public:
void operator()(){
cout << "id:" << id << endl;
++id; //OK
}
private:
int id; //copy of outside id
};


注意前面的函数e相当于将id设为const对象,因此不能更改id值,或者相当于operator()被定义为一个const成员函数。

猜你喜欢

转载自blog.csdn.net/owen7500/article/details/51387498