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


        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

    完。

  • 相关阅读:
    mysql root密码重置
    fetch跨域问题
    HTML5触摸事件(touchstart、touchmove和touchend)
    react-router-dom
    清理网站缓存
    从零开始学java (标识符,关键字,基本数据类型)
    从零开始学java ( 初始java)
    入职一年心得
    guava 函数式编程三兄弟
    java读取各种类型文件
  • 原文地址:https://www.cnblogs.com/warnet/p/10905835.html
Copyright © 2020-2023  润新知