VS2010 中的 C++ 嵌套 lambda 错误,带有 lambda 参数捕获?

Posted

技术标签:

【中文标题】VS2010 中的 C++ 嵌套 lambda 错误,带有 lambda 参数捕获?【英文标题】:C++ nested lambda bug in VS2010 with lambda parameter capture? 【发布时间】:2011-09-07 03:46:31 【问题描述】:

我正在使用 Visual Studio 2010,它显然在 lambdas 上有一些错误的行为,并且有这个嵌套的 lambda,其中内部 lambda 返回一个包装为 std::function 的第二个 lambda(参见"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 的捕获子句更改为“[&,n]”,则断言按预期通过。这是 VS2010 的错误还是我不明白 lambda 捕获是如何工作的?

【问题讨论】:

【参考方案1】:

这不是错误,因为 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!

【讨论】:

我实际上认为编译器应该能够警告这一点。 @mlimber :请记住,VC++ 2010 在N2927 之前实现了 lambda,因此它会有许多与嵌套 lambda 相关的“不正确”行为。 虽然在这种特殊情况下(有返回)你可能是正确的,嵌套的 Lambda 确实在 VS2010 中错误地失去了范围:connect.microsoft.com/VisualStudio/feedback/details/537366/… Microsoft 声称已经在他们的实现中应用了一个修复程序,我们'会在未来的版本中看到。【参考方案2】:

这类似于只返回一个简单引用的情况。引起你注意的是编译器没有发出警告。所以这不是编译器的错误,只是缺少警告。

std::function<int()> F(int n)

    return [&] return n; ;  //no warning

int& F2(int n)

    return n; //warning

【讨论】:

以上是关于VS2010 中的 C++ 嵌套 lambda 错误,带有 lambda 参数捕获?的主要内容,如果未能解决你的问题,请参考以下文章

VS Code 中的 Lambda 表达式 C++ 错误

使用C++在vs平台上编译了一个函数出现了如下情况,哪儿错了?怎么改?

为啥我在vs 2012 写c++的时候 定义一个常量,值是中文会报错,error: C2001: 常量中有换行符?

VS2008 中的 C++ 项目有效,但在 VS2010 中无效

VS2010 中的 C++ 智能感知

VS 2010 中的 C++ 调试访问冲突