i007.cc

i007.cc

优先队列-降维打击

05.价值资料

详解Lambda表达式的捕获

这段代码我之前给你写的例子是对的,我来确认一下其中的关键点,确保你完全理解 ✅


逐行解释

cpp
int count = 0;

auto counter = [count]() mutable {
    count++;
    return count;
};

 

  • [count] —— 值捕获:在 Lambda 定义的那一刻,把 count 的值(0)拷贝了一份,存在 Lambda 对象内部。
  • mutable —— 默认值捕获的副本是 const 的,不能修改。加上 mutable 后,这个副本变得可修改
  • 这个副本和外部的 count 从此再无关系——是完全独立的两块内存。

调用过程

cpp
counter();  // 内部副本:0 → 1,返回 1
counter();  // 内部副本:1 → 2,返回 2(注意:副本的状态被"记住"了!)

count;      // 外部的 count 仍是 0

 

关键点:Lambda 对象内部的 count 副本,在多次调用之间是持续存在的(因为它存储在 Lambda 对象本身里,不是每次调用重新初始化)。所以:

cpp
counter() 第一次调用 → 副本0+1=1
counter() 第二次调用 → 副本1+1=2(基于上次结果累加)

 

这其实让 counter 变成了一个带状态的计数器,很像一个微型的”闭包对象”。


可视化内存图

定义时:
┌─────────────┐         ┌─────────────┐
│ 外部 count=0 │         │ Lambda对象   │
└─────────────┘         │  内部副本=0  │ ← mutable,可改
                         └─────────────┘

调用两次后:
┌─────────────┐         ┌─────────────┐
│ 外部 count=0 │ (不变)   │ Lambda对象   │
└─────────────┘         │  内部副本=2  │ ← 累计变化
                         └─────────────┘

 


验证一下:如果不加 mutable 会怎样?

cpp
auto counter = [count]() {
    count++;   // ❌ 编译错误!
    return count;
};

 

报错大致是:

error: increment of read-only variable 'count'

 

因为没有 mutable,值捕获的副本默认是 const int count,不允许修改。


这个用法实际有什么用?

cpp
// 生成一个独立计数器,每次调用自增
auto makeCounter = []() {
    int id = 0;
    return [id]() mutable {
        return ++id;
    };
};

auto counterA = makeCounter();
auto counterB = makeCounter();

counterA();  // 1
counterA();  // 2
counterB();  // 1(counterB 有自己独立的副本,互不影响!)

 

这其实就是用 Lambda 实现了一个轻量级的闭包工厂,每个 Lambda 实例都有自己独立的状态。

你的理解完全正确!有什么具体疑问,还是想看更多 mutable 的应用场景?

发表回复