移动语意及非移动语意下的函数返回过程分析
c++11的移动语意特性带来了很多好处,其中之一,就是让参数的“传递”更加自然,参数到了这里就真的像是“传”进了方法。应用在构造函数上,很大程度上提升了对象构造的效率。这点在大对象时的体现尤其明显。与此同时,编译器的RVO(return value optimization ),也给方法返回值提供了类似移动语意的编译器级别优化。为了更好的理解这个过程,写了两段示例代码,分别使用了移动构造函数和拷贝构造函数,来分析对象的传递和构造过程。
代码1,拷贝构造函数
1 /** 2 * compile cmd: g++ -g -o test a.cc -std=c++0x -fno-elide-constructors 3 */ 4 #include <iostream> 5 6 class my 7 { 8 public: 9 int a {1}; 10 11 public: 12 my() 13 { 14 std::cout << "ctor_@" << this << std::endl; 15 } 16 my(const my& m) 17 { 18 std::cout << "cpy_ctor_src@" << &m << ";rcv@" << this << std::endl; 19 a = m.a; 20 } 21 ~my() 22 { 23 std::cout << "dtor_@" << this << std::endl; 24 } 25 my& operator = (const my& m) 26 { 27 std::cout << "operator=_src@" << &m << ";rcv@" << this << std::endl; 28 a = m.a; 29 return *this; 30 } 31 }; 32 33 my get_my() 34 { 35 my _m = my(); 36 return _m; 37 } 38 39 /** 40 * 可能的输出,及分析如下 41 * ctor_@0x7fff2bd494c0 _n 42 * ctor_@0x7fff2bd49490 get_my()->my()临时变量 43 * cpy_ctor_src@0x7fff2bd49490;rcv@0x7fff2bd49480 get_my()->_m 函数局部变量 44 * dtor_@0x7fff2bd49490 45 * cpy_ctor_src@0x7fff2bd49480;rcv@0x7fff2bd494f0 get_my()返回值临时变量 46 * dtor_@0x7fff2bd49480 47 * operator=_src@0x7fff2bd494f0;rcv@0x7fff2bd494c0 get_my()返回值临时变量->_n 48 * dtor_@0x7fff2bd494f0 49 * dtor_@0x7fff2bd494c0 _n 50 */ 51 int main() 52 { 53 my _n; 54 _n = get_my(); 55 return 0; 56 }
代码2,移动构造函数
1 /** 2 * compile cmd: g++ -g -o test moveable.cc -std=c++0x -fno-elide-constructors 3 */ 4 #include <iostream> 5 6 class HugeMem 7 { 8 public: 9 int* c; 10 int sz; 11 12 public: 13 HugeMem(int size): sz(size > 0? size: 1) 14 { 15 c = new int[sz]; 16 } 17 18 HugeMem(HugeMem&& hm) 19 { 20 c = hm.c; 21 sz = hm.sz; 22 hm.c = nullptr; 23 } 24 25 ~HugeMem() 26 { 27 delete [] c; 28 } 29 }; 30 31 class Moveable 32 { 33 public: 34 int* i; 35 HugeMem h; 36 37 public: 38 Moveable(): i(new int(3)), h(1024) 39 { 40 std::cout << "Moveable_nor_ctor_called_src@" << this << std::endl; 41 } 42 43 Moveable(Moveable&& m): i(m.i), h(std::move(m.h)) 44 { 45 std::cout << "Moveable_mov_ctor_called_src@" << &m << ";rcv@" << this << std::endl; 46 m.i = nullptr; 47 } 48 49 ~Moveable() 50 { 51 std::cout << "Moveable_dtor_called_src@" << this << std::endl; 52 delete [] i; 53 } 54 }; 55 56 #define output_moveable_addr(ma) \ 57 { \ 58 std::cout << std::hex << "huge_mem_from:" << __func__ << " @" << ma.h.c << std::endl; \ 59 } 60 61 Moveable get_temp() 62 { 63 Moveable tmp = Moveable(); 64 output_moveable_addr(tmp); 65 66 return tmp; 67 } 68 69 int main() 70 { 71 /** 72 * 一种可能的输出及结果分析 73 * 74 * Moveable_nor_ctor_called_src@0x7ffffecc3eb0 get_temp()->Moveable() 临时变量 75 * Moveable_mov_ctor_called_src@0x7ffffecc3eb0;rcv@0x7ffffecc3e90 get_temp()->临时变量 => get_temp()->tmp 76 * Moveable_dtor_called_src@0x7ffffecc3eb0 get_temp()->Moveable() 临时变量销毁 77 * huge_mem_from:get_temp @0x602030 78 * Moveable_mov_ctor_called_src@0x7ffffecc3e90;rcv@0x7ffffecc3f10 get_temp()->tmp => get_temp()返回值临时变量 79 * Moveable_dtor_called_src@0x7ffffecc3e90 get_temp()->tmp销毁 80 * Moveable_mov_ctor_called_src@0x7ffffecc3f10;rcv@0x7ffffecc3ef0 get_temp()返回值临时变量 => main()->a 81 * Moveable_dtor_called_src@0x7ffffecc3f10 get_temp()返回值临时变量销毁 82 * huge_mem_from:main @0x602030 83 * Moveable_dtor_called_src@0x7ffffecc3ef0 main()->a 销毁 84 */ 85 Moveable a(get_temp()); 86 output_moveable_addr(a); 87 88 return 0; 89 } 90 91 #undef output_moveable_addr
完。