捕获捕获本地临时性的lambda函数

Catching lambda functions capturing local temporaries

本文关键字:lambda 函数 临时性      更新时间:2023-10-16

我最近在我们的代码库中发现了几个Lambda,它们大部分时间都能工作,但依赖于未定义的行为。这里有一个例子:

#include <iostream>
#include <thread>
std::thread thread;
void foo(int bar)
{
    thread = std::thread([&]() { std::cout << bar << std::endl; });
}
int main(int argc, char* argv[])
{
    foo(5);
    thread.join();
}

问题是具有局部作用域(bar(的变量通过引用捕获,并在以后访问。奇怪的是,我们的编译器(GCC、Clang、MSVC(默认情况下都没有对此发出警告,即使它应该像"警告:返回本地临时对象的地址"一样容易被捕获。有没有办法让上述编译器对此发出警告?

这件事最近也引起了我的注意。我意识到我是通过引用bloomin'来捕获函数args的。

在这种情况下,我很想得到关于这一点的警告,但我怀疑我们没有得到警告的原因是,在许多情况下,捕获没有错。只要你立即执行lambda,你就安全了。只有当您存储它以供以后使用时(包括在工作线程中(,您才可能出现问题。

要么是编译器还不够聪明,要么是他们的作者决定不对此发出警告。

不管是什么情况,我不知道有任何主流编译器会对您的代码发出警告。所以你只需要非常小心。

您没有返回临时变量的地址。传递临时变量的引用是可以的。当然,当您通过引用线程传递变量时,如果最初传递临时变量的源函数已过期,则可能会导致意外结果。

但是,编译器并不关心线程的创建和线程顺序。因为人们可能会使用自己的线程库而不是std::thread。从编译器的角度来看,它只是寻找语言结构的有效性,而[&](...){}是一个有效的结构。

换句话说,编译器并没有办法捕捉到这个(实际上有用的(警告。遗憾的是,这是程序员的责任。您可以将argv复制到std::string对象并按值传递。