Ответ 1
Линия инициализации диапазона цикла for(:)
не продлевает срок службы ничего, кроме последнего временного (если есть). Любые другие временные файлы отбрасываются до выполнения цикла for(:)
.
Теперь, не отчаивайтесь; есть легкое решение этой проблемы. Но сначала пройдите через то, что идет не так.
Код for(auto x:exp){ /* code */ }
расширяется, в основном:
{
auto&& __range=exp;
auto __it=std::begin(__range);
auto __end=std::end(__range);
for(; __it!=__end;++__it){
auto x=*__it;
/* code */
}
}
(С скромной ложью на строках __it
и __end
, а все переменные, начиная с __
, не имеют видимого имени. Также я показываю версию на С++ 17, потому что я верю в лучший мир, и различия здесь не имеют значения.)
Ваш exp
создает временный объект, а затем возвращает ссылку внутри него. Временное умирает после этой строки, поэтому в остальной части кода у вас есть оборванная ссылка.
Фиксация относительно проста. Чтобы исправить это:
std::string const& func() const& // notice &
{
return m.find("key")->second;
}
std::string func() && // notice &&
{
return std::move(m.find("key")->second);
}
делать rvalue перегрузки и возвращать перемещенные значения по значению при использовании временных времен, вместо того, чтобы возвращать ссылки в них.
Тогда
auto&& __range=exp;
Строка ссылается на расширение жизненного цикла на возвращаемое значение string
и больше не обматывает ссылки.
Как правило, никогда не возвращайте диапазон по ссылке на параметр, который может быть значением r.
Приложение: Подождите, &&
и const&
после методов? rvalue ссылки на *this
?
С++ 11 добавлены ссылки rvalue. Но функция this
или self для функций является специальной. Чтобы выбрать, какая перегрузка метода основана на rvalue/lvalue-ness вызываемого объекта, вы можете использовать &
или &&
после окончания метода.
Это работает так же, как тип параметра для функции. &&
после того, как метод заявляет, что метод следует вызывать только на неконстантных значениях; const&
означает, что он должен вызываться для постоянных lvalues. Вещи, которые точно не совпадают, соответствуют обычным правилам соблюдения правил.
Когда у вас есть метод, который возвращает ссылку в объект, убедитесь, что вы улавливаете временные файлы с перегрузкой &&
и либо не возвращаете ссылку в этих случаях (возвращаете значение), либо =delete
метод.