In general, the C++ range-based for loop has the format as shown below:
for(range_declaration : range_expression) {
/* loop body*/
}
It is perfectly fine for range_expression to be something that results in a temporary. Take an example of that. The following loop is using a temporary and works as expected:
auto foo() { //returns by value
return std::initializer_list<int>{1,2,3};
}
for(auto i : foo()) //OK
std::cout << i;
But there is a saying, "sight is one of the most easily deceived senses." It is fine to use a range_expression that returns a temporary, but what happens if the range_expression has a temporary within it? Consider this seemingly innocuous code below:
/* returns a shared_ptr of vector by value */
auto getData() { //Requires C++14
auto ptr = std::make_shared<std::vector<int>>(10);
//range fill vector (0,1,2,3,4,5,6,7,8,9)
std::iota(ptr->begin(), ptr->end(), 0);
return ptr;
}
//Use getData somewhere else in range loop
for(auto i : *getData()) // Is it OK??
std::cout << i;
Bear in mind that, the getData() is returning an std::shared_ptr by value, not a std::vector by value. Therefore, the range-based for loop above is iterating over a temporary std::vector returned by dereferencing a temporary std::shared_ptr.
Select from below what would be the output of the above (check Explanations
for details):