• c++11中的move是否会改变对象的地址


    C++11中引入的移动语义,这个move操作是否会改变对象的地址,测试程序如下:

     1 #include <iostream>
     2 #include <string>
     3 #include <cstdio>
     4 
     5 using namespace std;
     6 
     7 string func(int n)
     8 {
     9     string s = "";
    10     for(int i = 0; i < n; i++)
    11         s += ('A' + i);
    12     cout << "in func , s : " << s << std::endl;
    13     printf("in func , s arrd : %lu
    ", (long unsigned int)&s);
    14     printf("in func , s data addr : %lu
    ", (long unsigned int)s.data());
    15     
    16     return std::move(s);
    17 }
    18 
    19 
    20 int main()
    21 {
    22     string ret = func(30);
    23     
    24     std::cout << "ret : " << ret << std::endl;
    25     printf("in main , ret addr : %lu
    ", (long unsigned int)&ret);
    26     printf("in main , ret data addr : %lu
    ", (long unsigned int)ret.data());
    27     
    28     return 0;
    29 }

    运行结果:

    可以看到,s的地址和ret的地址是不一样的,而它们底层引用的数据的地址是一样的。

    也就是说元数据的地址会改变,但是底层的真正存储数据的地址不变,这也是move的作用,减少底层的数据的拷贝。

    例子2:

     1 #include <iostream>
     2 #include <cstdio>
     3 
     4 using namespace std;
     5 
     6 class test_data
     7 {
     8 public:
     9     test_data()
    10     {
    11         std::cout << "test_data()" << std::endl;
    12     }
    13     
    14     test_data(const test_data& d)
    15     {
    16         std::cout << "test_data(const test_data& d)" << std::endl;
    17     }
    18     
    19     ~test_data()
    20     {
    21         std::cout << "~test_data()" << std::endl;
    22     }
    23 };
    24 
    25 
    26 test_data func()
    27 {
    28     test_data t;
    29     
    30     return t;
    31 }
    32 
    33 int main()
    34 {
    35     test_data ret = func();
    36     
    37     return 0;
    38 }

    结果1:

     

    结果一中,编译时禁止rvo优化,可以看到经历了一次构造,和两次拷贝构造。

     

    一次构造是28行的t构造,拷贝构造是func返回时,将结果拷贝构造给了临时对象,紧接着t析构,临时对象又拷贝构造给了ret,接着临时对象析构,最后ret析构。

     

     

     

    不禁止rvo优化的话,结果如下:

     

     

     

    下面添加move:

     

     

     1 #include <iostream>
     2 #include <cstdio>
     3 
     4 using namespace std;
     5 
     6 class test_data
     7 {
     8 public:
     9     test_data()
    10     {
    11         std::cout << "test_data()" << std::endl;
    12     }
    13     
    14     test_data(const test_data& d)
    15     {
    16         std::cout << "test_data(const test_data& d)" << std::endl;
    17     }
    18     
    19     ~test_data()
    20     {
    21         std::cout << "~test_data()" << std::endl;
    22     }
    23 };
    24 
    25 
    26 test_data func()
    27 {
    28     test_data t;
    29     
    30     return std::move(t);
    31 }
    32 
    33 int main()
    34 {
    35     test_data ret = func();
    36     
    37     return 0;
    38 }

     

    第30行添加了move。注意,没有实现移动构造。

    结果1:

     

     

     

     禁止rvo优化时加不加move都一样。

    结果2:

     

     

     

     开了rvo优化,只是少了临时对象的构造。

    现在看来,开了rvo优化不用move的时候,优化力度更强一些,那个时候只有一次构造和一次析构。

    使用move时,类应该有对应的移动构造函数才可以,新代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 
     4 using namespace std;
     5 
     6 class test_data
     7 {
     8 public:
     9     test_data()
    10     {
    11         p = new char[1024];
    12         std::cout << "test_data()" << std::endl;
    13     }
    14     
    15     test_data(const test_data& d)
    16     {
    17         p = new char[1024];
    18         std::cout << "test_data(const test_data& d)" << std::endl;
    19     }
    20     
    21     test_data(const test_data&& d)
    22     {
    23         p = d.p;
    24         const_cast<test_data&>(d).p = nullptr;
    25         std::cout << "test_data(const test_data&& d)" << std::endl;
    26     }
    27     
    28     ~test_data()
    29     {
    30         delete p;
    31         std::cout << "~test_data()" << std::endl;
    32     }
    33     
    34 public:
    35     char *p;
    36 };
    37 
    38 
    39 test_data func()
    40 {
    41     test_data t;
    42     
    43     std::cout << "in func , t addr : " << (long unsigned int)&t << std::endl;;
    44     std::cout << "in func , t data addr : " << (long unsigned int)t.p << std::endl;;
    45     
    46     return std::move(t);
    47 }
    48 
    49 int main()
    50 {
    51     test_data ret = func();
    52     
    53     std::cout << "in main , ret addr : " << (long unsigned int)&ret << std::endl;
    54     std::cout << "in main , ret data addr : " << (long unsigned int)ret.p << std::endl;
    55     
    56     return 0;
    57 }

    结果:

     

    如果只定义了移动构造而没有使用move,例如第46行直接是return t,这种情况下,编译器也会进行优化,还是会调用到移动构造。代码就改46这一行,运行结果:

     

     依然走到了移动构造。

    加上move只是让语义更加明确。

  • 相关阅读:
    抓包工具fiddler使用-初级
    nginx负载均衡配置详解
    nginx常用配置
    nginx介绍及常用功能
    算法分析实验之The Josephus Problem(约瑟夫问题)
    算法分析实验之Locker doors
    算法分析实验之花生采摘
    算法分析实验之俄式乘法
    算法分析实验之翻煎饼
    java(一)Hello World
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/13549724.html
Copyright © 2020-2023  润新知