简体   繁体   English

如果使用/ std:c ++ 17在MSVC2017 15.9.3中使用静态本地错误,lambda返回的值是多少?

[英]How is value returned by lambda using a static local wrong in MSVC2017 15.9.3 with /std:c++17?

The example code below prints values from a lambda function, which simply increments and returns the value of a static local counter variable. 下面的示例代码从lambda函数打印值,该函数简单地递增并返回静态局部计数器变量的值。

It prints 0,1 and 2,3 as expected with gcc and clang with C++17. 正如预期的那样打印0,12,3与gcc和clang与C ++ 17。 But not in Visual Studio Community 2017 15.9.3 with /std:c++17 set - it prints 0,0 and 2,3 instead. 但不是在Visual Studio Community 2017 15.9.3中使用/std:c++17设置 - 它会打印0,02,3

#include <iostream>

int main() {
    auto f = [] {
        static int i = 0;
        return i++;
    };
    const int v1 = f(); // Expect v1 = 0
    const int v2 = f(); // Expect v2 = 1

    // Prints the wrong values (MSVC 15.9.3 with /std:c++17)
    std::cout << v1 << "," << v2 << std::endl; // Expect "0,1", prints "0,0"

    // Prints the right values (or ought to with C++17 sequencing, anyway)
    std::cout << f() << "," << f() << std::endl; // Expect "2,3", prints "2,3"

    return 0;
}

The strange output (in x86 debug builds) 奇怪的输出(在x86调试版本中)

0,0
2,3

It looks like a compiler bug (so we filed the report): https://developercommunity.visualstudio.com/content/problem/347419/unexpected-return-from-lambda-with-static-local-va.html 它看起来像编译器错误(所以我们提交了报告): https//developercommunity.visualstudio.com/content/problem/347419/unexpected-return-from-lambda-with-static-local-va.html

In what way is the produced program wrong, such that it incorrectly prints 0 for both v1 and v2 , but correctly prints 2, 3 after that? 以什么方式生成的程序错误,这样它不正确地为v1v2打印0 ,但在那之后正确打印2, 3 Any educated guess at what the compiler bug is? 任何有根据的猜测编译器错误是什么?

As a workaround I used a capture instead: 作为一种解决方法,我使用了捕获:

auto f = [i = 0]() mutable {
    return i++;
};

UPDATE - as a side note, the output from the example above is different again in x86 release builds: 更新 - 作为旁注,上面示例的输出在x86发布版本中再次不同:

0,1
3,2

There is another existing issue with MSVC, where std::cout 's << operator is not sequenced left-to-right despite /std:c++17 being set, which I would speculate results in 3,2 being output here, at least. MSVC存在另一个问题,其中std::cout<<运算符从左到右排序,尽管/std:c++17被设置,我推测结果在这里输出3,2 ,至少。

MSVC compiles the following cleanly: MSVC干净地编译以下内容:

constexpr int foo() {
    static int i = 0;
    return i++;
}
static_assert(foo() == foo()); // oh no

That is not standards compliant. 符合标准。

So, what happens is that since C++17, lambdas are implicitly constexpr if they can be. 所以,会发生的事情是,自C ++ 17以来,lambdas隐含地是constexpr如果可以的话。 MSVC wrongly decides that the lambda is constexpr , and so folds f() into a constant for v2 (that it got from v1 ). MSVC错误地判断lambda是constexpr ,因此将f()折叠成v2的常量(从v1得到)。 It doesn't do this when you directly output it because it apparently doesn't eagerly evaluate constexpr stuff like gcc does (or uses some other heuristic that we can't know about). 当你直接输出它时它不会这样做,因为它显然没有急切地评估像gcc那样的constexpr内容(或使用我们无法知道的其他启发式)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM