С++ 11: Оператор на основе диапазона: срок действия "range-init"?
В последнем стандарте С++ это означает, что:
for (foo : bar)
baz;
эквивалентно:
{
auto && r = bar;
for ( auto it = r.begin(), end = r.end(); it != end; ++it )
{
foo = *it;
baz;
}
}
Если в вышесказанном выше приведен вызов функции, который возвращает коллекцию, например:
vector<string> boo();
т
for (auto bo : boo())
...
Не становится ли строка:
auto&& r = boo();
...
И поэтому временное возвращаемое значение boo() уничтожается в конце выражения "auto & & r = boo()", а затем r является ссылкой на запись в записи цикла.?? Правильно ли это рассуждение? Если нет, почему бы и нет?
Ответы
Ответ 1
Правильно ли это рассуждение? Если нет, почему бы и нет?
Верно до этого момента:
И поэтому временное возвращаемое значение boo() уничтожается в конце инструкции "auto & & r = boo()" [...]
Привязывание временного к ссылке продлевает срок его службы так, как это указано в ссылке. Таким образом, временное время сохраняется для всего цикла (что также объясняет, почему во всей конструкции есть дополнительный набор {}
: правильно ограничить время жизни этого временного).
Это согласно параграфу 5 § 12.2 стандарта С++:
Второй контекст - это когда привязка привязана к временному. временный, к которому привязана ссылка, или временное, которое является полный объект подобъекта, к которому привязана ссылка сохраняется за время существования ссылки, за исключением:
[различные исключения, которые здесь не применяются]
Это интересное свойство, которое позволяет злоупотреблять циклом диапазона для недиапазонных объектов: http://ideone.com/QAXNf
Ответ 2
Объяснение неверно, потому что boo
возвращает временный объект по значению. Привязывание этого временного объекта к ссылке означает, что время жизни временного расширения. Стандартная цитата (§ 12.2/5):
[...] Временное связывание ссылки или временное, являющееся полным объектом подобъекта, к которому привязана ссылка, сохраняется для времени жизни ссылки [...]
В случае, если boo
вернула ссылку, рассуждение было бы правильным. Примером выражения, возвращающего ссылку на временный, является string("a") += string("b")
; использование этого значения в цикле for
на основе диапазона приводит к поведению undefined.