Оптимизация возвращаемого значения может применяться всегда , то, что не может быть универсально применено, является Именованным Оптимизация возвращаемого значения. По сути, для оптимизации необходимо, чтобы компилятор знал , какой объект будет возвращен в месте создания объекта.
В случае RVO (где возвращается временное) это условие выполняется тривиально: объект создается в операторе return, и, в общем, он возвращается.
В случае NRVO вам придется проанализировать код, чтобы понять, может ли компилятор знать эту информацию или нет. Если анализ функции прост, есть вероятность, что компилятор ее оптимизирует (например, один оператор возврата, который не содержит условного выражения; несколько операторов возврата одного и того же объекта; несколько операторов возврата, таких как T f() { if (condition) { T r; return r; } else { T r2; return r2; } }
, когда компилятор знает, что r
или r2
будет возвращено ...)
Обратите внимание, что вы можете предполагать оптимизацию только в простых случаях, в частности, пример в Википедии может быть оптимизирован достаточно умным компилятором:
std::string f( bool x ) {
std::string a("a"), b("b");
if ( x ) return a;
else return b;
}
Может быть переписан компилятором в:
std::string f( bool x ) {
if ( x ) {
std::string a("a"), b("b");
return a;
} else {
std::string a("a"), b("b");
return b;
}
}
И компилятор может знать в это время, что в первом ответвлении a
должен быть создан вместо возвращаемого объекта, а во втором ответвлении то же самое относится к b
. Но я бы на это не рассчитывал. Если код сложный, предположим, что компилятор не сможет произвести оптимизацию.
РЕДАКТИРОВАТЬ : Есть один случай, который я не упомянул явно, компилятору не разрешено (в большинстве случаев, даже если это было разрешено, он не мог этого сделать), чтобы оптимизировать копию из аргумент функции для оператора return:
T f( T value ) { return value; } // Cannot be optimized away --but can be converted into
// a move operation if available.