繁体   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?

下面的示例代码从lambda函数打印值,该函数简单地递增并返回静态局部计数器变量的值。

正如预期的那样打印0,12,3与gcc和clang与C ++ 17。 但不是在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;
}

奇怪的输出(在x86调试版本中)

0,0
2,3

它看起来像编译器错误(所以我们提交了报告): https//developercommunity.visualstudio.com/content/problem/347419/unexpected-return-from-lambda-with-static-local-va.html

以什么方式生成的程序错误,这样它不正确地为v1v2打印0 ,但在那之后正确打印2, 3 任何有根据的猜测编译器错误是什么?

作为一种解决方法,我使用了捕获:

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

更新 - 作为旁注,上面示例的输出在x86发布版本中再次不同:

0,1
3,2

MSVC存在另一个问题,其中std::cout<<运算符从左到右排序,尽管/std:c++17被设置,我推测结果在这里输出3,2 ,至少。

MSVC干净地编译以下内容:

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

符合标准。

所以,会发生的事情是,自C ++ 17以来,lambdas隐含地是constexpr如果可以的话。 MSVC错误地判断lambda是constexpr ,因此将f()折叠成v2的常量(从v1得到)。 当你直接输出它时它不会这样做,因为它显然没有急切地评估像gcc那样的constexpr内容(或使用我们无法知道的其他启发式)。

暂无
暂无

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

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