emplace_back Vs push_back

emplace_back()是C++11的新特性

emplace_back()和push_back()的区别

  1. push_back() 在vector尾部添加一个元素时,首先会创建一个临时对象,然后再将这个临时对象移动或拷贝到 vector 中
    • 如果是拷贝的话,事后会自动销毁先前创建的这个临时元素
  2. emplace_back() 是直接在 vector 尾部创建这个元素,省去了移动或者拷贝元素的过程
  3. emplace_back()并不是任何场景效率都比 push_back()

emplace_back()效率更高的应用场景

在向 vector 中添加元素时(假设元素类型是一个类类型)

  1. 如果添加的是类类型的有参构造函数的参数类型对应的变量:
    • 如果通过 push_back() 方式添加,则会调用一次有参构造 + 一次移动构造 ,如果移动构造不可用则为拷贝构造
    • 如果通过 emplace_back() 方式添加,则只会调用一次有参构造
  2. 如果添加的是类类型的变量:
    • 不论是通过 push_back() 方式还是 emplace_back() 方式,都只会调用一次拷贝构造
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
class Person {
public:
int num;

public:
Person (int num) {
cout << __PRETTY_FUNCTION__ << endl;
this->num = num;
}

Person (const Person & p) {
cout << __PRETTY_FUNCTION__ << endl;
this->num = p.num;
cout << "num=" << this->num << endl;
}

Person (Person && p) noexcept {
cout << __PRETTY_FUNCTION__ << endl;
this->num = p.num;
p.num = 0;
cout << "num=" << this->num << endl;
}

~Person () {
cout << __PRETTY_FUNCTION__ << endl;
}
};

void test01() {

Person p1(1);
vector<Person> v;

cout << __LINE__ << endl;
v.push_back(10); // 会调用一次有参构造+一次移动构造

cout << __LINE__ << endl;
v.emplace_back(20); // 会调用一次有参构造

cout << __LINE__ << endl;
v.push_back(p1); // 会调用一次拷贝构造

cout << __LINE__ << endl;
v.emplace_back(p1); // 会调用一次拷贝构造
}

int main(){
test01();
return 0;
}

以有参构造中的参数类型的变量作为实参来使用 push_back()emplace_back() ,可以提升效率,但我认为这种实参形式不易于理解

References

http://c.biancheng.net/view/6826.html

https://blog.csdn.net/unonoi/article/details/114680819?spm=1001.2101.3001.6650.5&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-5-114680819-blog-119282296.235%5Ev38%5Epc_relevant_anti_t3_base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-5-114680819-blog-119282296.235%5Ev38%5Epc_relevant_anti_t3_base&utm_relevant_index=9