11 July 2022

C++ 核心指南目录

F.53: Avoid capturing by reference in lambdas that will be used non-locally, including returned, stored on the heap, or passed to another thread

理由

局部的指针和引用,不可以超出其范围而存在。 lambda 的通过引用捕获只是在另一个地方存放指向局部对象的引用,不可以超出其范围而存在。

例子

int local = 42;

// Want a reference to local.
// Note, that after program exits this scope,
// local no longer exists, therefore
// process() call will have undefined behavior!
thread_pool.queue_work([&] { process(local); });

例子

int local = 42;
// Want a copy of local.
// Since a copy of local is made, it will
// always be available for the call.
thread_pool.queue_work([=] { process(local); });

注意

如果一定要捕获一个非局部的指针,可以考虑用unique_ptr,这样就确保了同步和生存周期问题。如果一定要捕获 this 指针,可以使用[*this]捕获,这样会产生整个对象的一个副本。

强化

  • (简单)如果 lambda 的捕获列表里有局部的变量的引用,则产生一个警告。
  • (复杂)如果捕获列表里有指向局部变量的引用,且该 lambda 又会传递给一个不是常值的,且不是本地的地方,则高亮标记。