[*this]不是自动深拷贝,而是调用类的复制构造函数进行值拷贝,要求类可复制且所有成员可复制,否则编译失败或产生浅拷贝陷阱。
![c++20 lambda怎么在捕获列表中支持[*this]值拷贝](https://img.php.cn/upload/article/001/221/864/179117824862510.png)
[*this] 是 C++17 引入、C++20 完全支持的语法,它在捕获列表中按值拷贝整个当前对象(而非仅拷贝 this 指针),从根本上规避悬空指针风险。但它的行为和限制比表面看起来更微妙——不是所有类都能直接用,也不是写了就一定安全。
为什么 [*this] 不是“自动深拷贝”
[*this] 触发的是当前对象的**复制构造**(或移动构造,若适用),不是递归克隆所有成员指向的内容。它只保证对象本身的数据成员被复制,不保证成员所含指针/句柄指向的资源也被复制。
- 如果类有
std::unique_ptr<T>成员,默认复制构造会编译失败(unique_ptr不可拷贝) - 如果类含裸指针成员(如
int*),复制后两个对象指向同一块内存——这不是“值语义”,而是浅拷贝陷阱 - 若类未定义复制构造函数,且编译器生成的默认版本不满足需求(比如含非平凡资源管理),
[*this]会编译失败或行为异常
[*this] 的实际使用条件
要让 [*this] 编译通过并按预期工作,必须同时满足:
- 当前类必须是**可复制的**:即拥有可访问、非删除的复制构造函数(显式定义 or 编译器隐式生成)
- 所有非静态数据成员都必须可复制(例如不能含
unique_ptr,除非你自定义了复制逻辑) - 若类含
mutable成员,它们也会被复制;但 lambda 内部修改副本不会影响原对象 - 必须在 C++17 或更高标准下编译(C++20 完全兼容,无需额外开关)
示例:class Widget { int x; std::string s; }; 可直接用 [*this];但若加一个 std::unique_ptr<int> p;,就得先重载复制构造函数,否则报错。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
常见错误:以为 [*this] 能绕过 const 限制
在 const 成员函数里写 [*this]() mutable { ... } 是合法的,但注意:
-
[*this]复制的是**调用时刻的 const 对象状态**,副本本身是非 const 的(所以mutable才允许修改) - 副本中的成员变量值是 const 函数调用时的快照,后续原对象变化不影响它
- 但如果原对象的某个成员是
mutable,它在副本里仍是mutable,但修改副本的该成员对原对象无影响
真正容易忽略的是:若类中某个成员本身是引用类型(int& ref;),[*this] 无法编译——引用成员不可复制,这是硬性限制,不是配置问题。
替代方案:什么时候该放弃 [*this]
当类不可复制,或复制代价过高(如含大数组、缓存等),[*this] 就不适用。此时更务实的选择是:
- 用
[self = std::shared_ptr<MyClass>(shared_from_this())](需继承std::enable_shared_from_this) - 手动按需捕获关键成员:
[x = this->x, s = this->s](C++14 初始化捕获) - 彻底解耦:把需要的数据提前提取为局部变量,再用
[x, s]值捕获
最后一句提醒:[*this] 看似一劳永逸,但它把整个对象的复制语义推给了类设计者。如果你没控制类的复制行为,就别指望 lambda 自己能兜底。

















