C++11 Lambda 表达式
外观
C++11 Lambda表达式[编辑 | 编辑源代码]
简介[编辑 | 编辑源代码]
Lambda表达式是C++11引入的一项重要特性,它允许在代码中定义匿名函数对象(也称为闭包)。Lambda表达式提供了一种简洁的方式来创建临时函数,特别适用于需要传递函数作为参数的场景(如STL算法、回调函数等)。与传统的函数指针和函数对象相比,Lambda更加灵活且语法更简洁。
Lambda表达式的主要特点包括:
- 可以捕获上下文变量
- 支持内联定义
- 自动推导返回类型(或在某些情况下显式指定)
- 可作为参数传递或存储在变量中
基本语法[编辑 | 编辑源代码]
Lambda表达式的基本语法如下:
[捕获列表](参数列表) -> 返回类型 {
// 函数体
}
其中:
- 捕获列表:指定哪些外部变量可以在Lambda体内使用,以及如何捕获它们(值捕获或引用捕获)
- 参数列表:与普通函数的参数列表类似
- 返回类型:可以省略(编译器自动推导),但在某些情况下需要显式指定
- 函数体:包含Lambda执行的代码
最简单的Lambda示例[编辑 | 编辑源代码]
#include <iostream>
int main() {
// 定义一个简单的Lambda,不捕获任何变量,无参数
auto greet = []() {
std::cout << "Hello, Lambda!" << std::endl;
};
// 调用Lambda
greet();
return 0;
}
输出:
Hello, Lambda!
捕获列表详解[编辑 | 编辑源代码]
Lambda表达式可以通过捕获列表访问外部作用域的变量。捕获方式有多种:
捕获语法 | 描述 |
---|---|
[ ] |
不捕获任何变量 |
[=] |
以值捕获所有变量(隐式值捕获) |
[&] |
以引用捕获所有变量(隐式引用捕获) |
[x] |
仅以值捕获x |
[&x] |
仅以引用捕获x |
[=, &x] |
默认以值捕获,但x以引用捕获 |
[&, x] |
默认以引用捕获,但x以值捕获 |
捕获示例[编辑 | 编辑源代码]
#include <iostream>
int main() {
int x = 10;
int y = 20;
// 值捕获x,引用捕获y
auto lambda = [x, &y]() {
std::cout << "x (值捕获): " << x << ", y (引用捕获): " << y << std::endl;
y++; // 可以修改y,因为它是引用捕获
};
lambda();
std::cout << "调用后 y 的值: " << y << std::endl;
return 0;
}
输出:
x (值捕获): 10, y (引用捕获): 20 调用后 y 的值: 21
参数与返回类型[编辑 | 编辑源代码]
Lambda表达式的参数列表和返回类型与普通函数类似,但有几点特殊之处:
自动返回类型推导[编辑 | 编辑源代码]
当Lambda体只包含一个return语句时,返回类型可以省略:
auto square = [](int x) { return x * x; };
显式指定返回类型[编辑 | 编辑源代码]
当Lambda体包含多个return语句或复杂逻辑时,应显式指定返回类型:
auto absolute = [](int x) -> int {
if (x >= 0)
return x;
else
return -x;
};
实际应用案例[编辑 | 编辑源代码]
与STL算法结合[编辑 | 编辑源代码]
Lambda表达式常与STL算法一起使用,使代码更简洁:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用Lambda作为谓词
auto is_even = [](int n) { return n % 2 == 0; };
// 统计偶数数量
int count = std::count_if(numbers.begin(), numbers.end(), is_even);
std::cout << "偶数数量: " << count << std::endl;
// 就地修改vector
std::for_each(numbers.begin(), numbers.end(), [](int &n) { n *= 2; });
// 输出结果
for (int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
输出:
偶数数量: 2 2 4 6 8 10
作为回调函数[编辑 | 编辑源代码]
Lambda非常适合作为回调函数使用:
#include <iostream>
#include <functional>
void process_data(int x, int y, std::function<void(int)> callback) {
int result = x + y;
callback(result);
}
int main() {
process_data(5, 3, [](int result) {
std::cout << "处理结果: " << result << std::endl;
});
return 0;
}
输出:
处理结果: 8
高级特性[编辑 | 编辑源代码]
可变Lambda (mutable)[编辑 | 编辑源代码]
默认情况下,值捕获的变量在Lambda内是const的。使用mutable
关键字可以修改这些副本:
#include <iostream>
int main() {
int x = 0;
auto counter = [x]() mutable {
x++; // 修改捕获的副本
std::cout << "计数: " << x << std::endl;
return x;
};
counter(); // 计数: 1
counter(); // 计数: 2
std::cout << "原始x: " << x << std::endl; // 原始x未被修改
return 0;
}
输出:
计数: 1 计数: 2 原始x: 0
泛型Lambda (C++14)[编辑 | 编辑源代码]
虽然这是C++14特性,但值得一提。Lambda可以使用auto
参数:
auto multiply = [](auto a, auto b) { return a * b; };
性能考虑[编辑 | 编辑源代码]
Lambda表达式通常会被编译器内联优化,性能与普通函数相当。但需要注意:
- 捕获大量变量或大对象可能影响性能
- 引用捕获需要注意生命周期问题
- 复杂的Lambda可能影响编译器优化
总结[编辑 | 编辑源代码]
Lambda表达式是C++11引入的强大特性,它:
- 简化了函数对象的创建
- 使代码更简洁易读
- 便于与STL算法配合使用
- 支持灵活的变量捕获方式
掌握Lambda表达式可以显著提高现代C++编程的效率和代码质量。