Предположим, что у меня есть функция, которая возвращает значение std::vector по значению:
std::vector<int> buildVector();
Казалось бы естественным перебирать результат с использованием диапазона for:
for (int i : buildVector()) {
// ...
}
Вопрос: Безопасно ли это сделать?
Мое чтение стандарта (на самом деле, черновик n4431) предполагает, что это может быть не так, хотя мне тяжело полагая, что комитет не смог разрешить это использование. Я надеюсь, что мое чтение неверно.
В разделе 6.5.4 определяется диапазон for:
for ( for-range-declaration : expression ) statement
со следующим обессериванием:
{
auto && __range = range-init;
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin ) {
for-range-declaration = *__begin;
statement
}
}
где range-init является просто ( expression ) и, по крайней мере, для типов классов, begin-expr является либо __range.begin(), либо begin(__range) и т.д.
В моем примере buildVector я думаю, что range-init создает временное значение, которое реализация может быть уничтожена сразу после привязки ссылки __range. Это означало бы, что ссылка __range может уже свисать с временем begin-expr.
Конечно, всегда должно быть безопасно написать это:
std::vector<int> notATemporary = buildVector();
for (int i : notATemporary) {
// ...
}
Но я надеюсь, что мне не нужно добавлять это в свой список gotchas.