-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmove.cpp
More file actions
290 lines (277 loc) · 8.56 KB
/
Copy pathmove.cpp
File metadata and controls
290 lines (277 loc) · 8.56 KB
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
//
// Created by william on 2021/3/28.
//
#include "base.h"
#include <utility>
#include <vector>
/// 可作为面试题:可参考链接:https://segmentfault.com/q/1010000008984307
/// move的语义是经由移动构造函数创建的副本,本质上是强转,如果没有移动构造函数,还是会走拷贝构造函数。
class StringTest
{
public:
StringTest()
{
std::cout << "constructor" << std::endl;
}
explicit StringTest(std::string s) :
m_s(std::move(s))
{
std::cout << "constructor()" << std::endl;
}
~StringTest()
{
std::cout << "distructor" << std::endl;
}
StringTest(const StringTest&)
{
std::cout << "copy constructor" << std::endl;
}
StringTest(const StringTest&&) noexcept
{
std::cout << "move constructor" << std::endl;
}
private:
[[maybe_unused]] std::string m_s;
};
[[maybe_unused]] void moveTest()
{
std::string str = "hello";
std::vector<std::string> v;
v.push_back(str);
// 使用push_back(const T&)重载
// 表示我们将带来复制str的成本
std::cout << "After copy, str is \"" << str << "\"\n";
// 使用右值引用 push_back(T&&)重载
// 表示不复制字符串,而是
// str的内容被移动进vector
// 这个开销可能比较低,但是也意味着str现在可能为空
v.emplace_back(std::move(str));
std::cout << "After move, str is \"" << str << "\"\n";
std::cout << "The contents of the vector are \"" << v[0]
<< "\", \"" << v[1] << "\"\n";
StringTest test;
StringTest test2;
std::vector<StringTest> v1;
std::cout << "1========v1.push_back(test)=========" << std::endl;
v1.push_back(test);
std::cout << "1========v1.emplace_back(test)=========" << std::endl;
v1.emplace_back(test);
std::cout << "1========v1.push_back(std::move(test))" << std::endl;
v1.push_back(std::move(test));
std::cout << "1========v1.emplace_back(test2)=========" << std::endl;
v1.emplace_back(test2);
std::cout << "1========v1.emplace_back(std::move(test2))" << std::endl;
v1.emplace_back(std::move(test2));
std::cout << "1========v1.emplace_back(\"hello\")=========" << std::endl;
v1.emplace_back("hello");
/// 注意v1.reserve(10);这一句很关键,vector扩容,一开始容量是0,第一次操作扩容到1,第二次是翻倍为2,会造成拷贝
/// 所以在你执行第一次push_back时,检查了容量不够,执行__push_back_slow_path函数,vector扩容到1,并且执行了一次移动构造函数,因为原来的vector是空的,所以不需要进一步处理。
/// 此时第一次打印 copy constructor
/// 在执行第二次emplace_back时,检查了容量不够,执行__push_back_slow_path函数,vector扩容到2,并且执行了一次拷贝构造函数。
v1.reserve(10);
std::cout << "2========v1.push_back(test)=========" << std::endl;
v1.push_back(test);
std::cout << "2========v1.emplace_back(test)=========" << std::endl;
v1.emplace_back(test);
std::cout << "2========v1.push_back(std::move(test))::good=========" << std::endl;
v1.push_back(std::move(test));
std::cout << "2========v1.emplace_back(test2)=========" << std::endl;
v1.emplace_back(test2);
std::cout << "2========v1.emplace_back(std::move(test2))::good=========" << std::endl;
v1.emplace_back(std::move(test2));
std::cout << "2========v1.emplace_back(\"hello\")=========" << std::endl;
v1.emplace_back("hello");
std::cout << "2========end=========" << std::endl;
/// 需要指的注意的是:在代码36行有没有加noexcept区别是很大的,这是是没加noexcept之前的结果
/**
* /Users/william/git/sample/cpp_demo/cmake-build-debug/cpp_demo
* After copy, str is "hello"
* After move, str is ""
* The contents of the vector are "hello", "hello"
* constructor
* constructor
* 1========v1.push_back(test)=========
* copy constructor
* 1========v1.emplace_back(test)=========
* copy constructor
* copy constructor
* distructor
* 1========v1.push_back(std::move(test))
* move constructor
* copy constructor
* copy constructor
* distructor
* distructor
* 1========v1.emplace_back(test2)=========
* copy constructor
* 1========v1.emplace_back(std::move(test2))
* move constructor
* copy constructor
* copy constructor
* copy constructor
* copy constructor
* distructor
* distructor
* distructor
* distructor
* 1========v1.emplace_back("hello")=========
* constructor()
* copy constructor
* copy constructor
* copy constructor
* copy constructor
* copy constructor
* copy constructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* 2========v1.push_back(test)=========
* copy constructor
* 2========v1.emplace_back(test)=========
* copy constructor
* 2========v1.push_back(std::move(test))::good=========
* move constructor
* 2========v1.emplace_back(test2)=========
* copy constructor
* 2========v1.emplace_back(std::move(test2))::good=========
* move constructor
* copy constructor
* copy constructor
* copy constructor
* copy constructor
* copy constructor
* copy constructor
* copy constructor
* copy constructor
* copy constructor
* copy constructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* 2========v1.emplace_back("hello")=========
* constructor()
* 2========end=========
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* Process finished with exit code 0
*/
/// 这是加了noexcept之后的结果,对比可以通过beyong compare对比一下,会发现move构造加了noexcept之后vector扩容打印出来的才是move构造
/**
*
* /Users/william/git/sample/cpp_demo/cmake-build-debug/cpp_demo
* After copy, str is "hello"
* After move, str is ""
* The contents of the vector are "hello", "hello"
* constructor
* constructor
* 1========v1.push_back(test)=========
* copy constructor
* 1========v1.emplace_back(test)=========
* copy constructor
* move constructor
* distructor
* 1========v1.push_back(std::move(test))
* move constructor
* move constructor
* move constructor
* distructor
* distructor
* 1========v1.emplace_back(test2)=========
* copy constructor
* 1========v1.emplace_back(std::move(test2))
* move constructor
* move constructor
* move constructor
* move constructor
* move constructor
* distructor
* distructor
* distructor
* distructor
* 1========v1.emplace_back("hello")=========
* constructor()
* move constructor
* move constructor
* move constructor
* move constructor
* move constructor
* move constructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* 2========v1.push_back(test)=========
* copy constructor
* 2========v1.emplace_back(test)=========
* copy constructor
* 2========v1.push_back(std::move(test))::good=========
* move constructor
* 2========v1.emplace_back(test2)=========
* copy constructor
* 2========v1.emplace_back(std::move(test2))::good=========
* move constructor
* move constructor
* move constructor
* move constructor
* move constructor
* move constructor
* move constructor
* move constructor
* move constructor
* move constructor
* move constructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* 2========v1.emplace_back("hello")=========
* constructor()
* 2========end=========
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* distructor
* Process finished with exit code 0
*
*/
}