L'optimisation de la valeur de retour peut toujours être appliqué, ce qui ne peut pas être appliqué universellement est Nommé Optimisation de la valeur de retour. Fondamentalement, pour que l'optimisation ait lieu, le compilateur doit connaître quel objet va être retourné à l'endroit où l'objet est construit.
Dans le cas de RVO (où un objet temporaire est retourné), cette condition est trivialement remplie : l'objet est construit dans l'instruction de retour, et bien, il est retourné.
Dans le cas de NRVO, il faudrait analyser le code pour comprendre si le compilateur peut connaître ou non cette information. Si l'analyse de la fonction est simple, il y a de fortes chances que le compilateur l'optimise (déclaration de retour unique qui ne contient pas de conditionnel, par exemple ; déclarations de retour multiples du même objet ; déclarations de retour multiples comme T f() { if (condition) { T r; return r; } else { T r2; return r2; } }
où le compilateur sait que r
o r2
sera être renvoyé...)
Notez que vous ne pouvez supposer l'optimisation que dans des cas simples. Plus précisément, l'exemple de wikipedia pourrait en fait être optimisé par un compilateur suffisamment intelligent :
std::string f( bool x ) {
std::string a("a"), b("b");
if ( x ) return a;
else return b;
}
Peut être réécrit par le compilateur en :
std::string f( bool x ) {
if ( x ) {
std::string a("a"), b("b");
return a;
} else {
std::string a("a"), b("b");
return b;
}
}
Et le compilateur peut savoir à ce moment-là que dans la première branche a
doit être construit à la place de l'objet retourné, et dans la deuxième branche, la même chose s'applique à b
. Mais je ne compterais pas là-dessus. Si le code est complexe, supposez que le compilateur ne sera pas en mesure de produire l'optimisation.
EDIT : Il y a un cas que je n'ai pas mentionné explicitement, le compilateur n'est pas autorisé (dans la plupart des cas, même s'il était autorisé, il ne pourrait pas le faire) à optimiser la copie d'un argument de la fonction vers l'instruction de retour :
T f( T value ) { return value; } // Cannot be optimized away --but can be converted into
// a move operation if available.