C++中返回对象的情形及RVO
http://www.cnblogs.com/xkfz007/archive/2012/07/21/2602110.html
之前有文章介绍过临时对象和返回值优化RVO方面的问题。见此处。
在C++中,返回对象这一点经常被诟病,因为这个地方的效率比较低,需要进行很多的操作,生成一些临时对象,如果对象比较大的会就会比较耗时。但是在编译器实现的时候,经常是对返回对象的情况进行优化,也就是进行返回值优化 。
在g++中,这个是默认已经进行了优化。以前我希望看看到底C++怎么操作的,但是无法看到,就是因为G++进行了默认的返回值优化RVO。今天在晚上发现可以有一中方法来禁止这个RVO,可以参考这儿。
具体来说就是在编译的时候,加上-fno-elide-constructors这个选项,
#include <iostream> using namespace std; class HasPtrMem { public: HasPtrMem(): d(new int(3)) { cout << "Construct: " << ++n_cstr << endl; } HasPtrMem(const HasPtrMem & h): d(new int(*h.d)) { cout << "Copy construct: " << ++n_cptr << endl; } HasPtrMem(HasPtrMem && h): d(h.d) { // 移动构造函数 h.d = nullptr; // 将临时值的指针成员置空 cout << "Move construct: " << ++n_mvtr << endl; } ~HasPtrMem() { delete d; cout << "Destruct: " << ++n_dstr << endl; } int * d; static int n_cstr; static int n_dstr; static int n_cptr; static int n_mvtr; }; int HasPtrMem::n_cstr = 0; int HasPtrMem::n_dstr = 0; int HasPtrMem::n_cptr = 0; int HasPtrMem::n_mvtr = 0; HasPtrMem GetTemp() { HasPtrMem h; cout << "Resource from " << __func__ << ": " << hex << h.d << endl; return h; } int main() { HasPtrMem a = GetTemp(); cout << "Resource from " << __func__ << ": " << hex << a.d << endl; }
编译执行:
g++ std_move4.cpp -std=c++11 $./a.out Construct: 1 Resource from GetTemp: 0x2572010 Resource from main: 0x2572010 Destruct: 1
添加 -fno-elide-constructors 选项,然后编译执行
$g++ std_move4.cpp -std=c++11 -fno-elide-constructors $./a.out Construct: 1 Resource from GetTemp: 0x6e7010 Move construct: 1 Destruct: 1 Move construct: 2 Destruct: 2 Resource from main: 0x6e7010 Destruct: 3
可以清晰的看到两次 Move construct 的执行