博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
移动构造函数和移动赋值函数
阅读量:7021 次
发布时间:2019-06-28

本文共 7951 字,大约阅读时间需要 26 分钟。

在一个类的内部同时实现常规拷贝构造函数和移动拷贝构造函数,常规赋值函数和移动赋值函数。

调用时若参数为一个左值,则调用常规函数;若参数为一个右值,则调用移动函数。
也可调用"std::move"强行调用移动函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <iostream>
#include <utility>
using 
std::cout;
using 
std::endl;
 
class 
Useless
{
private
:
    
int 
n;          
// number of elements
    
char 
* pc;      
// pointer to data
    
static 
int 
ct;  
// number of objects
public
:
    
Useless();
    
explicit 
Useless(
int 
k);
    
Useless(
int 
k, 
char 
ch);
    
Useless(
const 
Useless & f); 
// regular copy constructor
    
Useless(Useless && f);      
// move constructor
    
~Useless();
    
Useless operator+(
const 
Useless & f)
const
;
    
Useless & operator=(
const 
Useless & f); 
// copy assignment
    
Useless & operator=(Useless && f);      
// move assignment 
    
void 
ShowObject() 
const
;
};
// implementation
int 
Useless::ct = 0;
Useless::Useless()
{
    
cout << 
"enter " 
<< __func__ << 
"()\n"
;
    
++ct;
    
n = 0;
    
pc = nullptr;
    
ShowObject();
    
cout << 
"leave " 
<< __func__ << 
"()\n"
;
 
}
Useless::Useless(
int 
k) : n(k)
{
    
cout << 
"enter " 
<< __func__ << 
"(k)\n"
;
    
++ct; 
    
pc = 
new 
char
[n];
    
ShowObject();
    
cout << 
"leave " 
<< __func__ << 
"(k)\n"
;
}
Useless::Useless(
int 
k, 
char 
ch) : n(k)
{
    
cout << 
"enter " 
<< __func__ << 
"(k, ch)\n"
;
    
++ct;
    
pc = 
new 
char
[n];
    
for 
(
int 
i = 0; i < n; i++)
        
pc[i] = ch;
    
ShowObject();
    
cout << 
"leave " 
<< __func__ << 
"(k, ch)\n"
;
}
Useless::Useless(
const 
Useless & f): n(f.n) 
{
    
cout << 
"enter " 
<< __func__ << 
"(const &)\n"
;
    
++ct;
    
pc = 
new 
char
[n];
    
for 
(
int 
i = 0; i < n; i++)
        
pc[i] = f.pc[i];
    
ShowObject();
    
cout << 
"leave " 
<< __func__ << 
"(const &)\n"
;
}
Useless::Useless(Useless && f): n(f.n) 
{
    
cout << 
"enter " 
<< __func__ << 
"(&&)\n"
;
    
++ct;
    
pc = f.pc;       
// steal address
    
f.pc = nullptr;  
// give old object nothing in return
    
f.n = 0;
    
ShowObject();
    
f.ShowObject();
    
cout << 
"leave " 
<< __func__ << 
"(&&)\n"
;
}
Useless::~Useless()
{
    
cout << 
"enter " 
<< __func__ << 
"()\n"
;
    
ShowObject();
    
--ct;
    
delete 
[] pc;
    
cout << 
"leave " 
<< __func__ << 
"()\n"
;
}
Useless & Useless::operator=(
const 
Useless & f)  
// copy assignment
{
    
cout << 
"enter " 
<< __func__ << 
"(const &)\n"
;
    
ShowObject();
    
f.ShowObject();
    
if 
(
this 
== &f)
        
return 
*
this
;
    
delete 
[] pc;
    
n = f.n;
    
pc = 
new 
char
[n];
    
for 
(
int 
i = 0; i < n; i++)
        
pc[i] = f.pc[i];
    
ShowObject();
    
f.ShowObject();
    
cout << 
"leave " 
<< __func__ << 
"(const &)\n"
;
    
return 
*
this
;
}
Useless & Useless::operator=(Useless && f)       
// move assignment
{
    
cout << 
"enter " 
<< __func__ << 
"(&&)\n"
;
    
ShowObject();
    
f.ShowObject();
    
if 
(
this 
== &f)
        
return 
*
this
;
    
delete 
[] pc;
    
n = f.n;
    
pc = f.pc;
    
f.n = 0;
    
f.pc = nullptr;
    
ShowObject();
    
f.ShowObject();
    
cout << 
"leave " 
<< __func__ << 
"(&&)\n"
;
    
return 
*
this
;
}
Useless Useless::operator+(
const 
Useless & f)
const
{
    
cout << 
"enter " 
<< __func__ << 
"(const &)\n"
;
    
ShowObject();
    
f.ShowObject();
    
Useless temp = Useless(n + f.n);
    
for 
(
int 
i = 0; i < n; i++)
        
temp.pc[i] = pc[i];
    
for 
(
int 
i = n; i < temp.n; i++)
        
temp.pc[i] = f.pc[i - n];
    
cout << 
"\t temp: "
;
    
temp.ShowObject();
    
cout << 
"leave " 
<< __func__ << 
"(const &)\n"
;
    
return 
temp;
}
void 
Useless::ShowObject() 
const
    
cout << 
"\t this=" 
<< 
this 
<< 
", ct=" 
<< ct; 
    
cout << 
", pc=(" 
<< n << 
", " 
<< (
void
*)pc << 
", "
    
if 
(n == 0)
        
cout << 
"(object empty)"
;
    
else
        
for 
(
int 
i = 0; i < n; i++)
            
cout << pc[i];
    
cout << endl;
}
// application
int 
main()
{
    
Useless one(10, 
'x'
);
    
Useless two = one + one;   
// calls move constructor
    
cout << 
"object one:\n"
;
    
one.ShowObject();
    
cout << 
"object two:\n"
;
    
two.ShowObject();
    
Useless three, four;
    
cout << 
"three = one\n"
;
    
three = one;              
// automatic copy assignment
    
cout << 
"now object three:\n"
;
    
three.ShowObject();
    
cout << 
"and object one:\n"
;
    
one.ShowObject();
    
cout << 
"four = one + two\n"
;
    
four = one + two;         
// automatic move assignment
    
cout << 
"now object four:\n"
;
    
four.ShowObject();
    
cout << 
"four = move(one)\n"
;
    
four = std::move(one);    
// forced move assignment
    
cout << 
"now object four:\n"
;
    
four.ShowObject();
    
cout << 
"and object one:\n"
;
    
one.ShowObject();
     
 
std::cin.get();
}

测试结果如下。红色部分不是测试结果的一部分,是对测试结果的分析。

enter Useless(k, ch)

         this=0x7fffb5ade0f0, ct=1, pc=(10, 0x23f7010, xxxxxxxxxx
leave Useless(k, ch)
enter operator+(const &)
         this=0x7fffb5ade0f0, ct=1, pc=(10, 0x23f7010, xxxxxxxxxx
         this=0x7fffb5ade0f0, ct=1, pc=(10, 0x23f7010, xxxxxxxxxx
enter Useless(k)
         this=0x7fffb5ade100, ct=2, pc=(20, 0x23f7030, 
leave Useless(k)
         temp:   this=0x7fffb5ade100, ct=2, pc=(20, 0x23f7030, xxxxxxxxxxxxxxxxxxxx
leave operator+(const &)
object one:
         this=0x7fffb5ade0f0, ct=2, pc=(10, 0x23f7010, xxxxxxxxxx
object two:
         this=0x7fffb5ade100, ct=2, pc=(20, 0x23f7030, xxxxxxxxxxxxxxxxxxxx
         //"Useless two = one +one;"
         //首先调用"operator+(const &)",在这个函数内调用"Useless(k)"生成temp对象。
         //返回时调用拷贝构造函数生成一个临时匿名对象。
         //析构temp对象。
         //然后再调用移动拷贝构造函数,生成对象two。
         //析构临时匿名对象。
         //当前gcc版本是g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4,对编译过程做了改进,直接把temp对象和two对象当成一个对象,省去了后面四步。
enter Useless()
         this=0x7fffb5ade110, ct=3, pc=(0, 0, (object empty)
leave Useless()
enter Useless()
         this=0x7fffb5ade120, ct=4, pc=(0, 0, (object empty)
leave Useless()
three = one
enter operator=(const &)
         this=0x7fffb5ade110, ct=4, pc=(0, 0, (object empty)
         this=0x7fffb5ade0f0, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
         this=0x7fffb5ade110, ct=4, pc=(10, 0x23f7050, xxxxxxxxxx
         this=0x7fffb5ade0f0, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
leave operator=(const &)
now object three:
         this=0x7fffb5ade110, ct=4, pc=(10, 0x23f7050, xxxxxxxxxx
and object one:
         this=0x7fffb5ade0f0, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
four = one + two
enter operator+(const &)
         this=0x7fffb5ade0f0, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
         this=0x7fffb5ade100, ct=4, pc=(20, 0x23f7030, xxxxxxxxxxxxxxxxxxxx
enter Useless(k)
         this=0x7fffb5ade130, ct=5, pc=(30, 0x23f7070, 
leave Useless(k)
         temp:   this=0x7fffb5ade130, ct=5, pc=(30, 0x23f7070, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
leave operator+(const &)
//"four = one + two"首先调用"operator+(const &)"函数。在这个函数内生成temp对象。
//在返回"operator+(const &)"函数后,并没有生成一个临时匿名对象,也没有析构temp对象,而是直接以temp做参数调用移动拷贝函数"operator=(&&)"。
enter operator=(&&)
         this=0x7fffb5ade120, ct=5, pc=(0, 0, (object empty)
         this=0x7fffb5ade130, ct=5, pc=(30, 0x23f7070, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
         this=0x7fffb5ade120, ct=5, pc=(30, 0x23f7070, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
         this=0x7fffb5ade130, ct=5, pc=(0, 0, (object empty)
leave operator=(&&)
//在返回"operator=(&&)"函数后才析构temp对象。
enter ~Useless()
         this=0x7fffb5ade130, ct=5, pc=(0, 0, (object empty)
leave ~Useless()
now object four:
         this=0x7fffb5ade120, ct=4, pc=(30, 0x23f7070, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
four = move(one)
//"four = std::move(one);"强行调用移动赋值函数"operator=(&&)"。
//调用之后,four对象接管了one对象的内部资源(pc和n),one对象没有被析构,但内部资源被“掏空”了!
enter operator=(&&)
         this=0x7fffb5ade120, ct=4, pc=(30, 0x23f7070, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
         this=0x7fffb5ade0f0, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
         this=0x7fffb5ade120, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
         this=0x7fffb5ade0f0, ct=4, pc=(0, 0, (object empty)
leave operator=(&&)
now object four:
         this=0x7fffb5ade120, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
and object one:
         this=0x7fffb5ade0f0, ct=4, pc=(0, 0, (object empty)

//退出"main()"时,析构栈空间的对象。析构顺序与构造顺序相反。

enter ~Useless()
         this=0x7fffb5ade120, ct=4, pc=(10, 0x23f7010, xxxxxxxxxx
leave ~Useless()
enter ~Useless()
         this=0x7fffb5ade110, ct=3, pc=(10, 0x23f7050, xxxxxxxxxx
leave ~Useless()
enter ~Useless()
         this=0x7fffb5ade100, ct=2, pc=(20, 0x23f7030, xxxxxxxxxxxxxxxxxxxx
leave ~Useless()
enter ~Useless()
         this=0x7fffb5ade0f0, ct=1, pc=(0, 0, (object empty)
leave ~Useless()

      本文转自FrankNie0101 51CTO博客,原文链接:http://blog.51cto.com/frankniefaquan/1934754,如需转载请自行联系原作者

你可能感兴趣的文章
greenplum分区表查看所占空间大小[转]
查看>>
c# ffmpeg wrapper
查看>>
git工作流介绍--结合sourcetree
查看>>
新一代UEFI BIOS UEFI基础知识介绍 (1)
查看>>
阻止OSPF路由
查看>>
python实现的json数据以HTTP GET,POST,PUT,DELETE方式页面请求
查看>>
ubuntu系统下修改mysql数据目录
查看>>
Apache URL Rwrite
查看>>
kubernetes1.8.5集群安装(带证书)
查看>>
ttlsa教程系列之mongodb——(三)mongodb的增删查改
查看>>
shell脚本中实现自动判断用户有无密码
查看>>
自动生成sql代码
查看>>
Nginx打开目录浏览功能(autoindex)
查看>>
我的友情链接
查看>>
RHEL5.4下如何创建yum源,如何使用yum命令
查看>>
正则表达式的使用
查看>>
用JDBC写的对oracle数据库增删改查的小程序
查看>>
关于Nginx的一些优化
查看>>
J2EE系统异常的处理准则
查看>>
TCP三次握手连接及seq和ack号的正确理解
查看>>