[英]How is value returned by lambda using a static local wrong in MSVC2017 15.9.3 with /std:c++17?
下面的示例代码从lambda函数打印值,该函数简单地递增并返回静态局部计数器变量的值。
正如预期的那样打印0,1
和2,3
与gcc和clang与C ++ 17。 但不是在Visual Studio Community 2017 15.9.3中使用/std:c++17
设置 - 它会打印0,0
和2,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
以什么方式生成的程序错误,这样它不正确地为v1
和v2
打印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.