[c++] push_back和emplace_back的区别
程序员文章站
2022-03-21 17:04:20
...
介绍
emplace操作是C++11新特性,新引入的三个操作emplace_front、emplace 和 emplace_back,分别对应push_front、insert 和push_back,允许我们将元素放在容器头部、一个指定的位置和容器尾部[1]。
本文以emplace_back和push_back为例讲解两者的区别。
区别
- 调用push_back时,参数为元素类型的对象,这个对象被拷贝到容器中。
- 调用emplace_back时,参数与该元素类型构造函数的参数相同,会在容器管理的内存空间内直接创建对象。
使用场景
有类A如下:
class A
{
public:
A(int x) { x_ = x; };
A(const A& a) { x_ = a.x_; };
private:
int x_;
};
- 若push_back/emplace_back传递的参数为未被构造的对象,即在传递参数时构建对象,如
vec.push_back(A(1)) / vec.emplace_back(1)
,这种情况下两种方法涉及的操作为push_back
- 新建临时对象
- 将该临时对象拷贝至容器末尾
- 销毁该临时对象
emplace_back
- 在容器末尾新建对象
- 若push_back/emplace_back传递的参数为已被构造的对象,如
A a(1); vec.push_back(a) / vec.emplace_back(a)
,这种情况下两种方法涉及的操作相同:push_back
- 将该对象拷贝至容器末尾
emplace_back
- 将该对象拷贝至容器末尾
示例
代码:
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
A (int x = 0) { x_ = x; cout << "constructor : " << x_ << endl; };
A (const A& a) { x_ = a.x_; cout << "copy constructor : " << x_ << endl; };
~A () { cout << "destructor : " << x_ << endl; };
private:
int x_;
};
int main()
{
A a(2);
cout << "##### push_back #####" << endl;
vector<A> vec_push;
cout << "capacity : " << vec_push.capacity() << endl << endl;
vec_push.push_back(A(1)); // 未被构造的对象
cout << "capacity : " << vec_push.capacity() << endl << endl;
vec_push.push_back(a); // 已被构造的对象
cout << "capacity : " << vec_push.capacity() << endl << endl;
cout << "\n\n##### emplace_back #####" << endl;
vector<A> vec_emplace;
cout << "capacity : " << vec_emplace.capacity() << endl << endl;
vec_emplace.emplace_back(1); // 未被构造的对象
cout << "capacity : " << vec_emplace.capacity() << endl << endl;
vec_emplace.emplace_back(a); // 已被构造的对象
cout << "capacity : " << vec_emplace.capacity() << endl << endl;
cout << "\n\n##### exit #####" << endl;
return 0;
}
运行结果:
constructor : 2
##### push_back #####
capacity : 0
constructor : 1
copy constructor : 1
destructor : 1
capacity : 1
copy constructor : 2
copy constructor : 1 # 这次拷贝构造的开销由vector扩容引起
destructor : 1 # 这次析构的开销由vector扩容引起
capacity : 2
##### emplace_back #####
capacity : 0
constructor : 1
capacity : 1
copy constructor : 2
copy constructor : 1 # 这次拷贝构造的开销由vector扩容引起
destructor : 1 # 这次析构的开销由vector扩容引起
capacity : 2
##### exit #####
destructor : 1
destructor : 2
destructor : 1
destructor : 2
destructor : 2
参考
[1] C++11新特性emplace操作
[2] C++无序关联容器(一)-使用场合和常用函数
[3] emplace与insert
如有错误,请大家及时指正 ????