1. 为什么我们需要Lambda表达式
在C++11标准引入lambda表达式之前,我们处理回调函数或临时函数对象时通常需要编写独立的函数或仿函数(functor)。这种方式存在几个明显的痛点:
首先,代码分散。一个简单的逻辑可能需要在不同文件间跳转查看,比如排序比较函数、算法谓词等。我曾经维护过一个图像处理项目,其中光是各种像素比较函数就分散在7个不同文件中,查找和修改极其不便。
其次,仿函数的定义过于繁琐。为了使用std::sort等算法,我们不得不定义完整的结构体并重载operator()。下面是一个典型的仿函数示例:
cpp复制struct CompareByArea {
bool operator()(const Shape& a, const Shape& b) const {
return a.getArea() < b.getArea();
}
};
std::vector<Shape> shapes;
std::sort(shapes.begin(), shapes.end(), CompareByArea());
而lambda表达式可以将上述代码简化为:
cpp复制std::sort(shapes.begin(), shapes.end(),
[](const Shape& a, const Shape& b) { return a.getArea() < b.getArea(); });
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Lambda表达式的核心语法解析
一个完整的lambda表达式通常由以下部分组成:
cpp复制[capture_list](parameters) mutable -> return_type { body }
2.1 捕获列表详解
捕获列表决定了lambda如何访问外部变量,这是最容易出错的部分。捕获方式主要有:
[]:不捕获任何变量[=]:以值方式捕获所有变量[&]:以引用方式捕获所有变量[var]:仅以值方式捕获特定变量[&var]:仅以引用方式捕获特定变量
警告:引用捕获要特别小心生命周期问题。我曾遇到过一个崩溃案例,lambda被存入队列异步执行时,引用的局部变量早已销毁
