Skip to content

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副本可改但影响不到外部

常见面试题

  1. auto l=[=]{}; 逃逸出去引用悬垂吗?按值拷则不悬(拷了值),只有 [&] 才悬。
  2. [=] 捕的是对象拷贝还是引用?拷贝(除非是引用成员则存引用)。
  3. 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&&);autovector<bool> 的 operator[] 拿到代理对象类型。

四、C++11~20 常用语法速览(面试列举用)

C++11:auto/decltype、右值+移动、智能指针、lambda、range-for、enum class、nullptr、default/delete、constexpr、模板可变参、std::threadstd::functionstd::arraystd::unordered_*、原子。 C++14:泛型 lambda、auto 返回类型推导、make_uniquestd::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),避免背一堆名字却讲不出原理。

C++ 面试八股 · VitePress 版