我正在使用Visual Studio 2010,它显然在lambdas上有一些错误的行为,并且有这个嵌套的lambda,其中内部lambda返回包裹为std :: function的第二个lambda(cf. "Higher-order Lambda Functions" on MSDN) :
int x = 0;
auto lambda = [&]( int n )
{
return std::function<void()>(
[&] // Note capture
{
x = n;
}
);
};
lambda( -10 )(); // Call outer and inner lambdas
assert( -10 == x ); // Fails!
这个编译但在断言失败。具体来说,内部lambda中的n是未初始化的(0xCCCCCCCC),但x被成功修改为其值。如果我将内部lambda的capture子句更改为“[&amp;,n]”,则断言按预期传递。这是VS2010的一个错误还是我不明白lambda捕获是如何工作的?
答案 0 :(得分:8)
这不是一个错误,因为n
在lambdas return语句之后超出范围,因此通过引用捕获将在您使用它时失效。
int x = 0;
auto lambda = [&]( int n )
{
return std::function<void()>( // n is local to "lambda" and is destroyed after return statement, thus when you call the std::function, the reference capture of n is invalid.
[&]
{
x = n; // Undefined behaviour
}
);
};
auto tmp = lambda(-10);
// n is no longer valid
tmp(); // calling tmp which uses reference of n which is alrdy destroyed.
assert( -10 == x ); // Fails!
答案 1 :(得分:3)
这与仅返回简单引用的情况类似。抓住你的是编译器没有发出警告。所以它不是编译器中的错误,只是缺少警告。
std::function<int()> F(int n)
{
return [&]{ return n; }; //no warning
}
int& F2(int n)
{
return n; //warning
}