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
|
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <utility>
// 正确实现移动语义的示例类
class BestPracticeClass
{
private:
std::unique_ptr<int[]> data;
size_t size;
std::string name;
public:
// 构造函数
BestPracticeClass(const std::string& n, size_t s)
: data(std::make_unique<int[]>(s)), size(s), name(n)
{
for (size_t i = 0; i < size; ++i)
{
data[i] = static_cast<int>(i);
}
std::cout << "Constructed: " << name << std::endl;
}
// 拷贝构造函数
BestPracticeClass(const BestPracticeClass& other)
: data(std::make_unique<int[]>(other.size)), size(other.size), name(other.name + "_copy")
{
std::copy(other.data.get(), other.data.get() + size, data.get());
std::cout << "Copy constructed: " << name << std::endl;
}
// 移动构造函数 - 标记为noexcept
BestPracticeClass(BestPracticeClass&& other) noexcept
: data(std::move(other.data)), size(other.size), name(std::move(other.name))
{
other.size = 0; // 将源对象置于有效状态
std::cout << "Move constructed: " << name << std::endl;
}
// 拷贝赋值操作符
BestPracticeClass& operator=(const BestPracticeClass& other)
{
if (this != &other)
{
// 创建临时对象,然后交换(异常安全)
BestPracticeClass temp(other);
swap(temp);
std::cout << "Copy assigned: " << name << std::endl;
}
return *this;
}
// 移动赋值操作符 - 标记为noexcept
BestPracticeClass& operator=(BestPracticeClass&& other) noexcept
{
if (this != &other)
{
data = std::move(other.data);
size = other.size;
name = std::move(other.name);
other.size = 0;
std::cout << "Move assigned: " << name << std::endl;
}
return *this;
}
// 交换函数
void swap(BestPracticeClass& other) noexcept
{
std::swap(data, other.data);
std::swap(size, other.size);
std::swap(name, other.name);
}
// 析构函数
~BestPracticeClass()
{
std::cout << "Destructed: " << name << std::endl;
}
// 访问器
const std::string& getName() const { return name; }
size_t getSize() const { return size; }
bool isValid() const { return data != nullptr; }
void print() const
{
std::cout << "Object: " << name << ", size: " << size;
if (data && size > 0)
{
std::cout << ", first element: " << data[0];
}
std::cout << std::endl;
}
};
// 全局swap函数(ADL查找)
void swap(BestPracticeClass& a, BestPracticeClass& b) noexcept
{
a.swap(b);
}
void BestPracticesDemo()
{
std::cout << "=== Best Practices Demo ===" << std::endl;
// 1. 正确的移动语义实现
std::cout << "\n1. Proper move semantics implementation:" << std::endl;
BestPracticeClass obj1("original", 5);
obj1.print();
BestPracticeClass obj2 = std::move(obj1);
obj2.print();
std::cout << "obj1 after move - valid: " << obj1.isValid() << std::endl;
// 2. 容器中的移动语义
std::cout << "\n2. Move semantics in containers:" << std::endl;
std::vector<BestPracticeClass> container;
container.reserve(3); // 避免重新分配
container.emplace_back("item1", 10);
container.emplace_back("item2", 20);
BestPracticeClass temp("temp", 15);
container.push_back(std::move(temp));
std::cout << "Container contents:" << std::endl;
for (const auto& item : container)
{
item.print();
}
// 3. 函数参数和返回值
std::cout << "\n3. Function parameters and return values:" << std::endl;
auto factory = [](const std::string& name, size_t size) -> BestPracticeClass {
return BestPracticeClass(name, size);
};
auto processObject = [](BestPracticeClass obj) { // 按值传递,支持移动
obj.print();
return obj; // 返回值优化
};
BestPracticeClass created = factory("factory_created", 8);
BestPracticeClass processed = processObject(std::move(created));
processed.print();
}
// 移动语义的常见陷阱
void CommonPitfallsDemo()
{
std::cout << "\n=== Common Pitfalls Demo ===" << std::endl;
// 陷阱1:多次移动同一个对象
std::cout << "\n1. Multiple moves from same object:" << std::endl;
BestPracticeClass original("original", 5);
BestPracticeClass moved1 = std::move(original);
// BestPracticeClass moved2 = std::move(original); // 危险:从已移动的对象再次移动
std::cout << "After first move, original valid: " << original.isValid() << std::endl;
// 陷阱2:忘记std::move
std::cout << "\n2. Forgetting std::move:" << std::endl;
BestPracticeClass source("source", 3);
// BestPracticeClass dest = source; // 拷贝,不是移动
BestPracticeClass dest = std::move(source); // 正确的移动
// 陷阱3:移动const对象
std::cout << "\n3. Moving const objects:" << std::endl;
const BestPracticeClass constObj("const", 2);
// BestPracticeClass moved = std::move(constObj); // 实际上是拷贝,不是移动
// 陷阱4:返回局部变量时使用std::move
std::cout << "\n4. Unnecessary std::move on return:" << std::endl;
auto badFactory = []() -> BestPracticeClass {
BestPracticeClass local("local", 4);
return std::move(local); // 不必要,阻止了RVO
};
auto goodFactory = []() -> BestPracticeClass {
BestPracticeClass local("local", 4);
return local; // 编译器会自动优化
};
BestPracticeClass result = goodFactory();
result.print();
}
// 移动语义的设计指导原则
void DesignGuidelinesDemo()
{
std::cout << "\n=== Design Guidelines Demo ===" << std::endl;
std::cout << "Move semantics design guidelines:" << std::endl;
std::cout << "1. Always mark move operations as noexcept when possible" << std::endl;
std::cout << "2. Leave moved-from objects in a valid but unspecified state" << std::endl;
std::cout << "3. Implement move operations for resource-owning classes" << std::endl;
std::cout << "4. Use std::move only when you want to transfer ownership" << std::endl;
std::cout << "5. Don't return std::move(local_variable) from functions" << std::endl;
std::cout << "6. Consider the Rule of Five (destructor, copy ctor, copy assign, move ctor, move assign)" << std::endl;
std::cout << "7. Use smart pointers to automatically get move semantics" << std::endl;
std::cout << "8. Be careful with self-assignment in move operations" << std::endl;
// 演示智能指针的自动移动语义
std::cout << "\nSmart pointer automatic move semantics:" << std::endl;
auto ptr1 = std::make_unique<int>(42);
std::cout << "ptr1 value: " << *ptr1 << std::endl;
auto ptr2 = std::move(ptr1);
std::cout << "After move, ptr1 is: " << (ptr1 ? "valid" : "null") << std::endl;
std::cout << "ptr2 value: " << *ptr2 << std::endl;
}
int main()
{
BestPracticesDemo();
CommonPitfallsDemo();
DesignGuidelinesDemo();
return 0;
}
|