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只是让语义更加明确。

原文地址:https://www.cnblogs.com/wanmeishenghuo/p/13549724.html