CppCoreGuidelines F.54 如果要在 lambda 里捕获 this 或成员变量,不要用 [=]
18 July 2022
F.54: When writing a lambda
that captures this
or any class data
member, don’t use [=]
default capture
理由
违反此规则,会产生混乱不清的代码。在成员函数里用[=]
捕获变量,看起来好像没问题。但是其实这种方式也会捕获到隐藏的 this
指针。而通过 this
指针是可以修改对象成员变量的。如果你通过 this
修改了对象成员变量,就相当于是进行了引用捕获。所以写代码的时候最好更明确一些。
例子
// -*- compile-command: "g++ -std=c++20 code.cpp && ./a"; -*- #include <iostream> #include <gsl/gsl> using namespace std; using namespace gsl; class My_class { int x = 0; void f() { int i = 0; // ... auto lambda = [=] { use(i, x); }; // BAD: "looks like" copy/value capture // [&] has identical semantics and copies the this pointer // under the current rules // [=,this] and [&,this] are not much better, and confusing x = 42; lambda(); // calls use(0, 42); x = 43; lambda(); // calls use(0, 43); // ... auto lambda2 = [i, this] { use(i, x); }; // ok, most explicit and least confusing // ... } };
注意
如果想要捕获成员数据的副本,可以考虑C++17的 [*this]
强化
如果 lambda
用了默认捕获,且可能会捕获到 this
指针。给代码打上一个警告标记。