Suppose I have a function that returns a std::vector
by value:
std::vector<int> buildVector();
It would seem natural to iterate over the result using a range-based for
:
for (int i : buildVector()) {
// ...
}
Question: Is it safe to do so?
My reading of the standard (actually, draft n4431) suggests that it might not be, though I'm having a hard time believing that the committee failed to allow for this usage. I'm hoping that my reading is incorrect.
Section 6.5.4 defines the range-based for
:
for ( for-range-declaration : expression ) statement
with the following desugaring:
{
auto && __range = range-init;
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin ) {
for-range-declaration = *__begin;
statement
}
}
where range-init
is just ( expression )
, and at least for class types, begin-expr
is either __range.begin()
or begin(__range)
, etc.
In my buildVector
example, I think the range-init
produces a temporary, which the implementation is allowed to destroy immediately after the __range
reference is bound. This would mean that the __range
reference might already be dangling by the time begin-expr
is evaluated.
Certainly, it should always be safe to write this:
std::vector<int> notATemporary = buildVector();
for (int i : notATemporary) {
// ...
}
But I'm hoping I don't have to add this to my list of gotchas.