RVO(返回值优化)是否适用于所有对象?
RVO( 返回值优化 )是保证还是适用于C ++编译器(特别是GCC)中的所有对象和情况?
如果答案是“否”,那么这个类/对象的优化的条件是什么? 我如何强制或鼓励编译器对特定的返回值执行RVO?
返回值优化可以始终应用,不能普遍应用的是命名返回值优化。 基本上,要进行优化,编译器必须知道在构造对象的地方将返回哪个对象。
在RVO(返回临时)的情况下,该条件被平凡地满足:对象在return语句中被构造,并且被返回。
在NRVO的情况下,您将不得不分析代码以了解编译器是否可以知道该信息。 如果函数的分析很简单,那么编译器可能会优化它(单个返回语句不包含条件语句,例如同一个对象的多个返回语句;多个返回语句如T f() { if (condition) { T r; return r; } else { T r2; return r2; } }
其中编译器知道r
或r2
将被返回…)
请注意,在简单情况下,您只能假定优化,具体而言,wikipedia中的示例实际上可以通过足够智能的编译器进行优化:
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
。 但我不会指望这一点。 如果代码复杂,则假定编译器将无法产生优化。
编辑 :有一个我没有明确提到的情况下,编译器是不允许的(在大多数情况下,即使它被允许,它不可能做到这一点)来优化从参数到函数的副本的返回语句:
T f( T value ) { return value; } // Cannot be optimized away --but can be converted into // a move operation if available.
RVO(返回值优化)保证gcc编译器中的所有对象?
没有任何优化能够得到保证 (虽然RVO是相当可靠的,但确实存在一些抛出它的情况 )。
如果答案是“否”,那么这个类/对象的优化的条件是什么?
一个相当有意从你的抽象实现细节。
既不知道也不关心这个,请。
对Jesper来说:如果要构build的对象很大,避免复制可能是必要的(或者至less是非常可取的)。
如果RVO发生,则避免复制,而不需要再写入任何代码。
如果没有,你必须手动做,自己写脚手架。 这可能会涉及到事先指定一个缓冲区,迫使你写这个空的(可能是无效的,你可以看到这是不干净的)对象和一个方法来构造这个无效的对象的构造函数。
所以'它可以减less我的代码行,如果它有保证。 不是吗? 并不意味着马苏德是个白痴。 不幸的是,他不能保证RVO。 你必须testing它是否发生,如果没有,写脚手架和污染你的devise。 它不能被殴打。
R值参考 (C ++ 11的新function)是解决您的问题的方法,它允许您使用Type(Type &&r);
( 移动构造函数 ),而不是Type(const Type &r)
( 复制构造函数 )。
例如:
class String { public: char *buffer; String(const char *s) { int n = strlen(s) + 1; buffer = new char[n]; memcpy(buffer, s, n); } ~String() { delete [] buffer; } String(const String &r) { // traditional copy ... } String(String &&r) { buffer = r.buffer; // O(1), No copying, saves time. r.buffer = 0; } }; String hello(bool world) { if (world) { return std::move( String("Hello, world.") ); } else { return std::move( String("Hello.") ); } } int main() { String foo = hello(); std::cout <<foo.buffer <<std::endl; }
这不会触发复制构造函数 。
EDIT1
代码
return std::move( String(...) );
可以缩短到
return String(...);
由于临时对象默认是R-value-ref。
我没有答案,也没有答案,但是如果你正在寻找的优化得到保证,你可以写更less的代码。
如果您编写需要编写的代码,程序将始终工作,如果优化在那里,它将运行得更快。 如果确实存在这样一种情况:优化“填补了空白”而不是代码的机制,并使其工作,或彻底改变逻辑,这似乎是一个错误,我想要固定,而不是实现细节我想依靠或利用。