前言
push_back与emplace_back都是vector容器中的方法,他们都可以实现在容器末尾添加一个新元素,但emplace_back方法作为c++11的新特性方法,在性能上要比push_back有一定的提升
测试
首先声明一个测试类,类内只有两个成员,并定义构造函数、拷贝构造函数与移动构造函数
class Person {
string m_name;
int m_age;
public:
Person() {};
Person(string name, int age) :m_name(name), m_age(age) {
cout << "构造函数..." <<m_name<<" " << m_age << endl;
}
Person(const Person& p)
{
this->m_name = p.m_name;
this->m_age = p.m_age;
cout << "拷贝构造函数..." << m_name << " " << m_age << endl;
}
Person(Person&& p)
{
this->m_name = p.m_name;
this->m_age = p.m_age;
cout << "移动构造函数..." << m_name << " " << m_age << endl;
}
};
push_back测试
首先使用push_back方法将person类假如vector中
cout << "---------\npush_back" << endl;
Person p("张三", 1);
vp1.push_back(p);
cout << "---------\npush_back" <<endl;
vp2.push_back(Person("李四",2));
emplace_back测试
再使用emplace_back方法将person类添加到vector中
cout << "---------\nemplace_back" << endl;
vp3.emplace_back("王五",3);
完整代码
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class Person {
string m_name;
int m_age;
public:
Person() {};
Person(string name, int age) :m_name(name), m_age(age) {
cout << "构造函数..." <<m_name<<" " << m_age << endl;
}
Person(const Person& p)
{
this->m_name = p.m_name;
this->m_age = p.m_age;
cout << "拷贝构造函数..." << m_name << " " << m_age << endl;
}
Person(Person&& p)
{
this->m_name = p.m_name;
this->m_age = p.m_age;
cout << "移动构造函数..." << m_name << " " << m_age << endl;
}
};
void sol() {
vector<Person> vp1;
vector<Person> vp2;
vector<Person> vp3;
cout << "---------\npush_back" << endl;
Person p("张三", 1);
vp1.push_back(p);
cout << "---------\npush_back" <<endl;
vp2.push_back(Person("李四",2));
cout << "---------\nemplace_back" << endl;
vp3.emplace_back("王五",3);
}
int main() {
sol();
return 0;
}
运行结果
结果分析
由上述运行结果可以看到
使用vp1使用push_back时,c++首先调用构造函数构造出person类实例p("张三",1),之后再调用拷贝构造函数拷贝出p的一个副本,再将这个副本添加到vector中,即vector中添加的是p的副本,而每向vector中添加一个对象都需要调用一次拷贝构造函数首先拷贝出对象实例的副本,再将副本放入vector中,可以想见,当类实例占用内存很大时,这种拷贝机制是很耗时的。
至于在vp2使用push_back时调用移动构造函数的原因是,vp1中push_back传入的参数是一个左值p,而vp2使用push_back时传入的是一个右值,即首先创建一个临时对象temp=Person("李四",2),之后再调用移动构造函数将temp作为参数传入push_back中。
而与之形成对比的是
emplace_back函数只是调用了一次构造函数,并没有拷贝副本放入vector中,也并不需要调用移动构造函数将一个右值传入vector中,原因是emplace_back直接在容器中构造对象,而不需要拷贝一个复制品将其放入vector中,从而实现了内存优化。
总结
- push_back():向容器尾部添加一个元素,首先调用构造函数构造出这个对象,再调用拷贝构造函数或者移动构造函数再向vector中传入该对象。适用于在容器中添加已经存在的元素。
- emplace_back():在容器尾部添加一个元素,直接调用构造函数原地构造,不需要触发拷贝构造和移动构造。因此比push_back()更加高效。适用于直接在容器中添加元素。