C++11 核心特性实战
在 C++11 标准引入的诸多革命性特性中,简化代码编写与统一可调用对象管理是两大核心目标。Lambda 表达式解决了传统仿函数定义繁琐、复用性低的痛点,让局部场景下的自定义逻辑(如排序规则、回调函数)能以更简洁的匿名函数形式实现;可变参数模板打破了模板参数数量固定的限制,为 STL 容器(如 emplace_back)和通用函数设计提供了灵活的参数处理能力;而 function 包装器与 bind 函数,则进一步整合了函数指针、仿函数、lambda 等不同类型的可调用对象,实现了统一管理与参数适配,甚至让可调用对象存储到容器中成为可能。
这些特性并非孤立存在——Lambda 的底层依赖仿函数实现,可变参数模板为 emplace 系列接口提供了技术支撑,function 与 bind 则基于前两者的特性,解决了'不同可调用对象类型不统一'的问题。本文将从实际开发需求出发,先讲解 Lambda 表达式的语法规则与捕获逻辑,再深入可变参数模板的展开方法与应用场景,最后通过 function 包装器与 bind 函数的实例,展示如何统一管理各类可调用对象、灵活调整参数顺序与固定参数值。
Lambda 表达式
在实际开发中,如果一个类包含多个成员变量需要排序,但每次比较逻辑不同,且每次都写一个独立的仿函数类显然太麻烦。这时 Lambda 表达式就派上用场了。
Lambda 表达式本质上是局部的匿名函数对象,因此可以直接填入 sort 等算法需要的仿函数位置。其底层实现依然依赖于仿函数机制。
需要注意的是,Lambda 表达式不存在重载的说法。例如 auto f1 = [](){} 和 auto f2 = [](){},即使看起来类型相同,f1 和 f2 也不是同一类型,直接赋值会报错。这意味着 Lambda 表达式之间不能相互赋值。
语法结构
[捕捉列表](参数列表)(mutable)-> 返回值类型 { 函数体 };
- 捕捉列表:用于捕捉表达式所在域的局部变量。全局域变量无需捕捉即可直接使用。强行捕捉可能会报错。
- 参数列表:如果不传参,
()可以省略。注意使用mutable修饰符时,参数列表不能省略。 - mutable:取消捕获列表中变量的默认 const 性。但如果捕获的对象本身是 const 的,加了 mutable 也无法修改。
- 返回值类型:通常编译器可以推导,一般可以省略。
捕获列表详解
若未使用 mutable,捕获的变量在 Lambda 内部均不可修改。
[var]:值传递方式捕捉变量 var,类型与外部一致。[=]:值传递方式捕获所有父作用域中的变量(包括 this)。[&var]:引用传递捕捉变量 var。例如[&x, &y]。[&]:引用传递捕捉所有父作用域中的变量(包括 this)。- 混合模式:如
[&, x],表示只有 x 是值传递,其他都是引用。 - 注意:捕捉列表不允许变量重复传递,否则会导致编译错误(如
[=, a]是不合法的)。
可调用对象的存储
Lambda 表达式作为可调用对象的一种,配合 function 包装器,可以与函数指针、仿函数一起存储到容器中。
可变参数模板
可变参数模板允许模板参数具有不确定数目,虽然日常手写较少,但在 STL 源码中非常常见。
template<class... Args>
void ShowList(Args... args) {
}


