С++ 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.