push_back与emplace_back
1#include <iostream>
2#include <vector>
3using namespace std;
4
5class A {
6public:
7 A() = default;
8 A(string name) : _name(name) { cout << "ctor: " << _name << endl; }
9 ~A() { cout << "dtor: " << _name << endl; }
10 // 拷贝构造函数
11 A(const A &other) { _name += "cp-" + other._name; cout << "cp-ctor: " << _name << endl; }
12 // 赋值运算符
13 A& operator=(const A &other) {
14 if (this != &other) {
15 _name += "cp-" + other._name;
16 cout << "cp-op: " << _name << endl;
17 }
18 return *this;
19 }
20 // 移动构造函数
21 A(A &&other) noexcept { _name += "mv-" + other._name; cout << "mv-ctor: " << _name << endl; }
22 // 移动赋值运算符
23 A& operator=(A &&other) noexcept {
24 if (this != &other) {
25 _name += "mv-" + other._name;
26 cout << "mv-op: " << _name << endl;
27 }
28 return *this;
29 }
30
31 string _name;
32};
33
34int main()
35{
36 vector<A> arr;
37 arr.reserve(100); // 重要!重新分配内存时可能导致测试结果有迷惑性
38
39 printf("==== push_back(\"a1\") ====\n");
40 arr.push_back(string("a1"));
41 printf("\n==== emplace_back(\"a2\") ====\n");
42 arr.emplace_back(string("a2"));
43
44 printf("\n==== push_back/emplace_back(lvalue) ====\n");
45 A a3("a3");
46 arr.push_back(a3);
47 arr.emplace_back(a3);
48
49 printf("\n==== push_back/emplace_back(rvalue) ====\n");
50 A a4("a4");
51 arr.push_back(std::move(a4));
52 A a5("a5");
53 arr.emplace_back(std::move(a5));
54
55 printf("\n==== return ====\n");
56 return 0;
57}
输出为:
1==== push_back("a1") ====
2ctor: a1
3mv-ctor: mv-a1
4dtor: a1
5
6==== emplace_back("a2") ====
7ctor: a2
8
9==== push_back/emplace_back(lvalue) ====
10ctor: a3
11cp-ctor: cp-a3
12cp-ctor: cp-a3
13
14==== push_back/emplace_back(rvalue) ====
15ctor: a4
16mv-ctor: mv-a4
17ctor: a5
18mv-ctor: mv-a5
19
20==== return ====
21dtor: a5
22dtor: a4
23dtor: a3
24dtor: mv-a1
25dtor: a2
26dtor: cp-a3
27dtor: cp-a3
28dtor: mv-a4
29dtor: mv-a5
移动构造函数用noexcept修饰后,vector扩容时才会调用
为什么需要将移动构造函数和移动赋值运算符标记为noexcept
1#include <iostream>
2#include <vector>
3using namespace std;
4
5class A {
6public:
7 A() = default;
8 A(string name) : _name(name) { cout << "ctor: " << _name << endl; }
9 ~A() { cout << "dtor: " << _name << endl; }
10 // 拷贝构造函数
11 A(const A &other) { _name = "cp-" + other._name; cout << "cp-ctor: " << _name << endl; }
12 // 赋值运算符
13 A& operator=(const A &other) {
14 if (this != &other) {
15 _name = "cp-" + other._name;
16 cout << "cp-op: " << _name << endl;
17 }
18 return *this;
19 }
20 // 移动构造函数
21 A(A &&other) noexcept { _name = "mv-" + other._name; cout << "mv-ctor: " << _name << endl; }
22 // 移动赋值运算符
23 A& operator=(A &&other) noexcept {
24 if (this != &other) {
25 _name = "mv-" + other._name;
26 cout << "mv-op: " << _name << endl;
27 }
28 return *this;
29 }
30
31 string _name = "anonymous";
32};
33
34int main() {
35 vector<A> arr(4);
36 arr.reserve(4);
37 cout << "capacity: " << arr.capacity() << endl; // 4
38
39 A a1("a1");
40 A a2("a2");
41 arr.push_back(a1); // 触发vector内存的重新分配: 第5个元素调用cp-ctor
42 // 如果mv-ctor声明为noexcept,则前4个元素调用移动构造函数; 否则调用拷贝构造函数cp-ctor
43 arr.push_back(std::move(a2)); // 第6个元素调用mv-ctor
44 cout << "capacity: " << arr.capacity() << endl; // 8
45
46 cout << "==== return ====" << endl;
47}
输出信息为:
1capacity: 4
2ctor: a1
3ctor: a2
4cp-ctor: cp-a1
5mv-ctor: mv-anonymous
6dtor: anonymous
7mv-ctor: mv-anonymous
8dtor: anonymous
9mv-ctor: mv-anonymous
10dtor: anonymous
11mv-ctor: mv-anonymous
12dtor: anonymous
13mv-ctor: mv-a2
14capacity: 8
15==== return ====
16dtor: a2
17dtor: a1
18dtor: mv-anonymous
19dtor: mv-anonymous
20dtor: mv-anonymous
21dtor: mv-anonymous
22dtor: cp-a1
23dtor: mv-a2