返回捕获lambda的lambda时发出Clang警告
以下尝试包装 lambda 的(简化)代码向我提供了一些 Clang 版本的警告,但不是全部,也不是 gcc。
template<typename Lambda>
auto wrapLambda(Lambda lambda)
{
return [&lambda]() {
lambda();
};
}
auto wrappedLambda = wrapLambda([](){ return 0; });
warning: address of stack memory associated with parameter 'lambda' returned [-Wreturn-stack-address]
return [&lambda]() {
^~~~~~
这是一个错误,还是我错过了什么?我x86-64 clang (trunk)在Godbolt 中收到警告,并clang version 11.1.0作为更大的回购的一部分,但我无法隔离该版本的故障。
这个相关问题中的例子没有给出警告。
改进(我认为)版本:
template<typename Callable>
auto wrapCallable(Callable&& callable)
{
return [callable = std::forward<Callable>(callable)]() {
callable();
};
}
auto wrappedCallable = wrapCallable([](){ return 0; });
这沉默的警告与x86-64 clang (trunk)在godbolt。我认为它应该对任何函子安全地工作,我遗漏了什么?
回答
问题与此代码完全相同:
SomeType& foo(int x)
{
SomeType bar{x};
return bar; // undefined behavior returning reference to local object
}
您的 lambda 正在通过引用捕获本地对象,因此当您返回它时,这将导致未定义的行为,因为捕获的对象不再存在。
当您使用此 lambda 时,程序很可能会崩溃(如果您不走运,则不会)。
所以这是您代码中的错误,clang 正在正确抱怨。
问题更新
后编辑:更新问题后,新代码会为 lambda 创建参数的副本(或移动副本)。结果是返回的 lambda 不携带对局部变量的引用,所以现在很好。