在lambda表达式用*this捕获对象副本

在lambda表达式用*this捕获对象副本
枫在lambda表达式用*this捕获对象副本
C++17 允许在 lambda 捕获列表中使用
*this。它的含义不是捕获this指针,而是按值捕获当前对象的一个副本。这个特性主要用来解决 lambda 延迟执行时,原对象已经变化甚至已经销毁带来的问题。
1. 先看 this 捕获是什么
在类成员函数里,lambda 很常见:
1 | class Test |
这里捕获的是 this 指针。
也就是说,lambda 里面访问的仍然是原对象本身。
2. *this 又是什么?
[*this] 则不同,它会把当前对象拷贝一份到 lambda 里。
1 | auto f = [*this]() { |
这样 lambda 内部操作的是对象副本,不是原对象。
3. 为什么这个特性重要?
如果 lambda 只是当前函数里立即执行,那么 [this] 一般没什么问题。
但如果 lambda 会被保存起来、异步执行、或者放到线程里延后执行,问题就来了:
- 原对象可能已经销毁
- 原对象的数据可能已经被修改
而 [*this] 能让 lambda 拿到一个当时的快照副本,减少这类风险。
4. 基本示例
1 |
|
这里即使后面原对象状态变化,lambda 内拿到的仍然是创建时拷贝进去的值。
5. 和 [this] 的区别
[this]
- 捕获的是指针
- 访问的是原对象
- 原对象变化,lambda 看到的内容也会变化
- 原对象销毁后继续调用 lambda,可能有风险
[*this]
- 捕获的是对象副本
- 访问的是拷贝后的对象
- 原对象后续变化,不影响 lambda 内部状态
- 更适合异步或延迟执行场景
6. 一个更直观的对比例子
1 |
|
输出通常会表现为:
1 | this: 99 |
这就很清楚了。
7. 适合用在什么场景?
7.1 异步任务
如果 lambda 交给线程池、回调队列或者异步接口执行,用 [*this] 往往更安全。
7.2 需要保留对象创建当时状态
有些逻辑本来就需要一个“快照”,而不是实时访问当前对象。
7.3 避免悬空指针风险
当原对象生命周期不容易保证时,值捕获副本通常更稳。
8. 使用时的注意点
8.1 会发生对象拷贝
这一点不能忽略。
如果对象很大,或者拷贝代价很高,那 [*this] 可能并不合适。
8.2 副本和原对象不是同一个对象
你在 lambda 里改副本,并不会影响外部原对象。
8.3 对象必须可拷贝
如果类禁用了拷贝构造,那 [*this] 就不能直接这样用。
总结
[*this] 可以理解成“把当前对象按值打包进 lambda”。
它和 [this] 最大的区别不在语法,而在语义:前者拿的是副本,后者拿的是原对象地址。对于异步回调、延迟执行和状态快照场景,这个特性还是很实用的。














