В общем, я хотел бы знать, когда и почему современный компилятор, скажем, gcc 4.7 и выше с использованием c ++ 11, не может применить оптимизацию NVRO.
РЕДАКТИРОВАТЬ: Я упростил этот код по ошибке, не возвращая никаких локальных переменных. Лучший пример был представлен @ cooky451 ниже, см. ideone.com/APySue
Я видел некоторые фрагменты кода для ответов на другие вопросы, которые как таковые
A f(A&& v)
{
return v;
}
и они были изменены, чтобы быть
A f(A&& v)
{
return std::move(v);
}
потому что они сказали, что переданное значение, которое присваивается значению v, все еще является значением и может быть перемещено. Однако другие писали, что это удалит возможность NVRO. Wny это? Если компилятор знает, что временный объект возвращается, разве он не может создать его непосредственно на месте, ничего не перемещая? Я полагаю, я не понимаю, почему в первом случае будет NVRO, а не в 2-м. У меня могут быть неверные факты, поэтому возникает вопрос. Кроме того, я прочитал, что случай 2 был анти-паттерном по этой причине, и что вы не должны возвращать std :: move как это. Любое дополнительное понимание будет полезно. Мне сказали, что за кулисами компилятор создаст что-то вроде этого ниже:& __hidden__
это назначение функции, в данном случае myValue.
A myValue = f(A());
// behind the scenes pseudo code for direct in place construction
void f(A&& v, A& __hidden__ )
{
__hidden__ = v;
return;
}
Оба не будут использовать RVO, потому что это невозможно. Проблема в: && все еще только ссылка. Переменная, которую вы возвращаете, находится за пределами локальной области функции! Итак, без std :: move вы будете копировать, а с ним вы будете двигаться. Я бы посоветовал, между прочим, не ожидать чего-то для rvalue-ссылки, если вы не пишете конструктор перемещения / оператор присваивания или какой-либо совершенный код шаблона для пересылки. Просто возьмите это по значению. В некоторых случаях он имеет небольшие накладные расходы, но на самом деле он не будет значительным. И это делает код намного более читабельным. И проще, так как вызывающая сторона может копировать или перемещать аргументы, и вам не нужно указывать& Перегрузки.
Других решений пока нет …