C++11 引入了 lambda 表达式,它是一种定义和使用匿名函数对象的简便方式。Lambda 表达式与普通函数类似,也有参数列表、返回值类型和函数体,只是它的定义方式更简洁,并且可以在函数内部定义。
Lambda 表达式的语法如下:
[capture] (parameters) -> return_type { function_body }
其中:
capture
是捕获列表,它指定了哪些外部变量可以在 lambda 函数体内使用。parameters
是参数列表,与普通函数的参数列表类似。return_type
是返回值类型,可以省略,由编译器推断。function_body
是函数体,包含了 lambda 函数的具体逻辑。首先看一下这个面试题
int v = 19;
auto f1 = [v]{return v;}; // 值捕获
auto f2 = [=]{return v;}; // 隐式捕获值
auto f3 = [&v]{return v;}; // 引用捕获
auto f4 = [&]{return v;}; // 隐式捕获引用
v = 10;
std::cout << f1() << " " << f2() << " " << f3() << " " << f4() << std::endl;
此题输出结果是 19 19 10 10
引用捕获传递的是引用,后边值修改后引用也会改变,值捕获传递的是此时此刻的值,后续做的修改不影响当前值
捕获列表中可以指定值捕获、引用捕获和隐式捕获三种方式:
[x]
表示以值的方式捕获外部变量 x
。下面是一个例子:#include
int main() {
int x = 10;
auto f = [x]() { std::cout << x << std::endl; };
x = 20;
f(); // 输出 10
return 0;
}
在上面的代码中,我们以值的方式捕获了外部变量 x
,并在 lambda 函数内部输出它的值。由于是以值的方式捕获,所以即使后面修改了 x
的值,lambda 函数内部仍然使用的是原来的值。
[&x]
表示以引用的方式捕获外部变量 x
。下面是一个例子:#include
int main() {
int x = 10;
auto f = [&x]() { std::cout << x << std::endl; };
x = 20;
f(); // 输出 20
return 0;
}
在上面的代码中,我们以引用的方式捕获了外部变量 x
,并在 lambda 函数内部输出它的值。由于是以引用的方式捕获,所以当后面修改了 x
的值时,lambda 函数内部也会使用新的值。
&
或 =
来指定隐式捕获所有外部变量。例如 [&]
表示以引用的方式隐式捕获所有外部变量,[=]
表示以值的方式隐式捕获所有外部变量。下面是一个例子:#include
int main() {
int x = 10, y = 20;
auto f1 = [&]() { std::cout << x << " " << y << std::endl; };
auto f2 = [=]() { std::cout << x << " " << y << std::endl; };
x = 30; y = 40;
f1(); // 输出 30 40
f2(); // 输出 10 20
return 0;
}
在上面的代码中,我们分别使用隐式引用捕获和隐式值捕获定义了两个 lambda 函数。当后面修改了 x
和 y
的值时,第一个 lambda 函数输出新的值,而第二个 lambda 函数输出原来的值。
需要注意的是,在使用引用捕获时,要确保被引用的对象在 lambda 表达式执行时仍然存在。此外,在 lambda 函数中修改值捕获的非静态局部变量时,需要在参数列表后面加上 mutable
关键字。
Lambda 表达式非常灵活强大,但也有一些需要注意的问题。例如,