Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it undefined behavior to iterate over an std::array initialized in the for-loop?

// 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

Is the first snippet undefined behavior, or is this a compiler bug?

Update: This was compiled with Visual Studio 16.7.2 and 16.7.3 using std=c++17 and /Ox. The error persists in my bug project, but I have not been able to reproduce it in a small project using similar build flags. The problem persist if I use integers instead of floating points.

like image 224
Viktor Sehr Avatar asked Sep 09 '20 09:09

Viktor Sehr


People also ask

How does range-based for loop work in C++?

C++11 introduced the ranged for loop. This for loop is specifically used with collections such as arrays and vectors. Here, the ranged for loop iterates the array num from beginning to end. The int variable var stores the value of the array element in each iteration.

What is Auto in C++ for loop?

Range-based for loop in C++ Often the auto keyword is used to automatically identify the type of elements in range-expression. range-expression − any expression used to represent a sequence of elements. Also Sequence of elements in braces can be used.

Are loops evaluated at compile time?

In general, for loops can't be compile -time evaluated. You're talking about a very specific case. But the same argument could then be used for just about any construct, not just for loops.

What is a ranged for loop?

Range-based for loop in C++ is added since C++ 11. It executes a for loop over a range. Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container.


Video Answer


1 Answers

No, it is not UB since range-for loop does extend lifetime of temporary range. https://en.cppreference.com/w/cpp/language/range-for

If range_expression returns a temporary, its lifetime is extended until the end of the loop, as indicated by binding to the forwarding reference __range, but beware that the lifetime of any temporary within range_expression is not extended.

Taking into consideration fact, that gcc has no problem with this code it is probably MSVC bug.

like image 157
bartop Avatar answered Oct 26 '22 16:10

bartop