返回值优化可以always可以应用,但不能普遍应用的是Named返回值优化。基本上,为了进行优化,编译器必须know在构造对象的地方将返回什么对象。
在 RVO 的情况下(返回临时值),这个条件很容易满足:在 return 语句中构造对象,并且返回它。
对于 NRVO,您必须分析代码以了解编译器是否可以知道该信息。如果函数的分析很简单,编译器很可能会对其进行优化(例如,不包含条件的单个返回语句;同一对象的多个返回语句;像这样的多个返回语句)T f() { if (condition) { T r; return r; } else { T r2; return r2; } }
编译器知道的地方r
or r2
will被退回...)
请注意,您只能假设在简单情况下进行优化,具体来说,维基百科中的示例实际上可以由足够聪明的编译器进行优化:
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
。但我不会指望这一点。如果代码很复杂,则假设编译器将无法产生优化。
EDIT:有一种情况我没有明确提到,编译器不允许(在大多数情况下即使允许,它也不可能做到)优化从函数参数到返回语句的副本:
T f( T value ) { return value; } // Cannot be optimized away --but can be converted into
// a move operation if available.