迭代在 for 循环中初始化的 std::array 是未定义的行为吗?

Vik*_*ehr 28 c++ floating-point stdarray

// This snippet
for (const float t : std::array{ 0.0f, 0.33f, 0.66f, 1.0f }) {
  std::cout << "t = " << t << "\n";
}
// Yields the following (incorrect) values:
t = -3.91649e-28
t = 4.59037e-41
t = 2.66247e-44
t = 0

// Whereas this snippet ...
auto vals = std::array{ 0.0f, 0.33f, 0.66f, 1.0f };
for (const float t : vals) {
  std::cout << "t = " << t << "\n";
}
// Yields the following (correct) values:
t = 0
t = 0.33
t = 0.66
t = 1
Run Code Online (Sandbox Code Playgroud)

第一个片段是未定义的行为,还是编译器错误?

更新: 这是使用 std=c++17 和 /Ox 使用 Visual Studio 16.7.2 和 16.7.3 编译的。该错误仍然存​​在于我的错误项目中,但我无法在使用类似构建标志的小项目中重现它。如果我使用整数而不是浮点数,问题仍然存在。

bar*_*top 21

不,它不是 UB,因为 range-for 循环确实延长了临时范围的生命周期。 https://en.cppreference.com/w/cpp/language/range-for

如果 range_expression 返回一个临时值,则其生命周期将延长到循环结束,如绑定到转发引用 __range 所指示的那样,但请注意,range_expression 内的任何临时值的生命周期都不会延长。

考虑到事实,gcc 对这段代码没有问题,它可能是 MSVC 错误。

  • 谢谢,那么这是MSVC在某些条件下的一个错误,试图研究如何在一个小项目中重现它。 (2认同)