移动语意及非移动语意下的函数返回过程分析

    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

 

完。

posted @ 2019-05-22 14:45  warnet  阅读(260)  评论(0编辑  收藏  举报