Проблема заключается в том, что вы создаете временный std::unordered_map
и возвращаете ссылку на одно из его содержимого. Давайте рассмотрим два поведения, которые происходят здесь:
1. На основе диапазона для расширения:
С вопрос, который вы связали в комментариях , мы видим, что следующий синтаксис:
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
}
}
Важной частью является понимание того, что когда вы создаете временное значение или предоставляете lvalue, будет создана ссылка на него (auto&& __range
). Если мы имеем дело с lvalues, мы приветствуем ожидаемые результаты. Однако когда range-init
возвращает временный объект, все становится немного интереснее. Мы сталкиваемся с продлением жизни .
2. Увеличение продолжительности жизни:
Это намного проще, чем может показаться. Если вы возвращаете временный объект для инициализации (связывания) ссылки на него, срок действия указанного объекта увеличивается, чтобы соответствовать времени жизни указанной ссылки . Это означает, что если range-init
возвращает временное значение, сохранение ссылки на него (__range
) продлевает время существования этого временного элемента до последней фигурной скобки кода, который я скопировал выше. Вот причина этих самых внешних скобок.
Ваш случай:
В вашем случае у нас довольно сложная ситуация. Проверка вашей петли:
for (const int i : std::unordered_map<int, std::vector<int>> {{0, std::vector<int> {1}}}.at(0)) {
std::cout << i << std::endl;
}
Мы должны признать две вещи:
- Вы создаете временную
std::unordered_map
. range-init
, не относящуюся к вашемуstd::unordered_map
. Это относится к тому, что .at(0)
retuns - значение от этой карты.
Это приводит к следующему следствию - время жизни вашей карты не продлено. Это означает, что его деструктор будет вызываться в конце полного выражения (в ;
из auto && __range = range-init;
). Когда вызывается std::unordered_map::~unordered_map
, он вызывает деструкторы всего, чем управляет - например, его ключи и значения. Другими словами, этот вызов деструктора вызовет деструктор вектора, на который вы получили ссылку посредством вызова at(0)
. Ваш __range
не является висячей ссылкой.