1. 为什么我们需要Lambda表达式
十年前我刚接触C++模板编程时,经常需要为简单的比较操作编写完整的函数对象类。记得有次为了实现一个字符串长度排序,不得不写一个带operator()的LengthComparator结构体,结果代码比实际业务逻辑还长。这种场景正是C++11引入lambda表达式的直接动因——让临时性的小函数能够就地定义,不再污染命名空间。
与传统的函数指针和函数对象相比,lambda有三大不可替代的优势:
- 就地定义:在需要函数的地方直接编写,避免跳转阅读
- 捕获上下文:自动获取外部变量,形成闭包
- 语法精简:比函数对象简洁90%以上的代码量
比如用lambda重写上述排序场景:
cpp复制std::vector<std::string> words = {"apple", "banana", "pear"};
std::sort(words.begin(), words.end(),
[](const auto& a, const auto& b) {
return a.length() < b.length();
});
2. Lambda表达式的完整语法解剖
一个标准的lambda表达式包含以下核心部件:
cpp复制[capture-list] (parameters) mutable -> return-type { body }
2.1 捕获列表的七种武器
捕获方式决定了外部变量的可见性:
[]空列表:不捕获任何变量[x]值捕获:创建x的拷贝[&x]引用捕获:直接操作x[=]隐式值捕获:所有变量拷贝[&]隐式引用捕获:所有变量引用[this]捕获当前类实例[*this](C++17) 捕获当前对象副本
警告:引用捕获可能导致悬垂引用。我曾调试过一个多线程场景下的崩溃问题,就是因为lambda被延迟执行时,局部变量已经销毁。
2.2 mutable关键字的玄机
默认情况下值捕获的变量是const的,添加mutable修饰后:
cpp复制int counter = 0;
auto f = [count
