Appearance
lambda 表达式 与 auto 类型推导
一、lambda 的语法与本质
cpp
[capture](params) -> return_type { body } // 省略可: [](int x){return x+1;}本质:lambda 是编译器生成的匿名函数对象(类),捕获变量会变成该类的成员。展开后约等于:
cpp
[&a](int x){ return a+x; }
// ≈ 生成:
class __lambda_xx {
int& a; // 捕获的变量作为成员
public:
int operator()(int x) const { return a + x; } // 重载 ()
};追问点:
- lambda 无捕获 → 可转成函数指针;有捕获 → 不行(状态函数对象)。
- 捕获成员类型由捕获方式定:
=(拷贝)拷成员,&(引用)存引用,故按值捕获的 lambda 拷贝构造函数可用。 - 按值捕获的变量默认 const(在 lambda 体内不能改),要改需
mutable。 - 捕获列表可以只捕
[this]/[a,b]/[=,&a]/捕获 this 访问其成员。 - 生命周期:按引用捕获了外部局部变量,但 lambda 在外部变量销毁后仍被调用 → 悬垂(同引用陷阱)。若 lambda 逃逸(存到全局/容器)要按值捕获或捕获 shared。
二、捕获方式对照
| 写法 | 捕获 | 是否能改捕获副本 |
|---|---|---|
[=] | 全部按值(仅用到的作用域变量) | 默认不可改(除非 mutable) |
[&] | 全部按引用 | 可改(改的是原对象) |
[a, &b] | a 按值、b 按引用 | a 副本不可改(mutable 才可) |
[this] | 捕获 this 指针 | 可改非 const 对象成员 |
[*this] (C++17) | 拷贝整个对象(this 指向对象副本) | 常与 async 配合避免悬垂 |
mutable | 使 operator() 非 const | 副本可改但影响不到外部 |
常见面试题:
auto l=[=]{};逃逸出去引用悬垂吗?按值拷则不悬(拷了值),只有[&]才悬。[=]捕的是对象拷贝还是引用?拷贝(除非是引用成员则存引用)。- lambda 与 std::function:lambda 是轻量函数对象可直接存 auto;
std::function做类型擦除,可能堆分配、更慢。把 lambda 存进容器/存储时常转为 std::function (小对象优化看实现)。
三、auto / constexpr 关于类型推导
auto 推导规则(多数推导同模板参数推导)
| 写法 | 结果 |
|---|---|
auto x = expr; | 剥掉引用与顶层 const:const int& y; auto a=y;→int |
auto& x = expr; | 保留引用,绝不剥 const/底层 |
auto&& x | 引用折叠:左值→T&,右值→T&&(万能) |
const auto& x | 显式加 const + 引用,配合避免拷贝 |
数组/函数:auto 从数组推导退化为指针 int*;auto& 保留数组 int(&)[N]。
decltype
decltype(expr) 保留原样(含引用、顶层 const、多余的括号影响:decltype((x)) 因多一层括号=表达式退化成 lvalue→变成 T&)。经典题:
cpp
int x;
decltype(x) a; // int
decltype((x)) b; // int& ← 括号使 x 变成左值表达式
auto c = x; // int推导替代与最佳实践
auto优点:少打字、防默认初始化错、配合 range-for/模板返回值。- 坑:
auto a = func();会拷贝返回值(若想避免拷贝用auto&&);auto由vector<bool>的 operator[] 拿到代理对象类型。
四、C++11~20 常用语法速览(面试列举用)
C++11:auto/decltype、右值+移动、智能指针、lambda、range-for、enum class、nullptr、default/delete、constexpr、模板可变参、std::thread、std::function、std::array、std::unordered_*、原子。 C++14:泛型 lambda、auto 返回类型推导、make_unique、std::integer_sequence。 C++17:结构化绑定、if/switch 内初始化、inline 变量、fold 表达式、std::optional/variant/any、filesystem、if constexpr。 C++20:concepts、coroutines、ranges、三向比较 <=>、span、consteval。
面试答「了解哪些 C++11 特性」:挑 3~5 个能展开讲原理的(移动语义、智能指针、lambda、auto、constexpr),避免背一堆名字却讲不出原理。