捕获lambda函数捕获当地临时值

时间:2016-08-04 08:56:15

标签: c++ lambda

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

#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)都没有默认警告,即使它应该像#34;警告一样容易捕获:返回本地临时对象的地址&#34;。有没有办法让任何提到的编译器对此发出警告?

2 个答案:

答案 0 :(得分:1)

最近这也引起了我的兴趣。我意识到我通过参考bloomin'到处来捕获函数args。

在这种情况下,我很想得到关于此事的警告,但我怀疑我们不这样做的原因是在很多情况下捕获没有任何问题。只要你立即执行lambda,你就安全了。只有在您将其存储以供以后使用时(包括在工作线程中),您才可能遇到问题。

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

无论如何,我都不知道任何主流编译器会对你的代码发出警告。所以你必须非常小心。

答案 1 :(得分:0)

您没有返回临时变量的地址。传递临时变量的引用很好。当然,当你通过引用传递变量时,如果源函数已经过期,那么它可能会导致意外的结果。

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

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