C++的vector中emplace_back() 与 push_back() 的区别
C++ 中 vector 的 emplace_back() 和 push_back() 均用于向容器末尾添加元素,但二者在实现和效率上有显著区别:
1. 参数传递方式
-  push_back():接受一个已构造的对象(左值或右值),将其拷贝或移动到容器中。std::vector<MyClass> v; MyClass obj(1, 2); v.push_back(obj); // 拷贝构造 v.push_back(MyClass(3, 4)); // 移动构造(临时对象是右值)
-  emplace_back():接受构造对象所需的参数列表,直接在容器内存中构造对象,无需临时对象。v.emplace_back(1, 2); // 直接调用 MyClass(int, int)
2. 效率对比
-  push_back()的潜在开销:- 若传递右值(如临时对象),会触发一次移动构造。
- 若传递左值,会触发一次拷贝构造。
- 需要先构造临时对象,再将其转移至容器。
 
-  emplace_back()的优势:- 直接在容器内存中构造对象,省去临时对象的创建和转移步骤,尤其对拷贝/移动成本高的对象(如大型类)效率更优。
 
3. 适用场景
-  优先使用 emplace_back():- 构造对象需要多个参数时,避免创建临时对象。
- 对象拷贝/移动成本高时。
- 需调用 explicit构造函数时(emplace_back支持直接初始化)。
 
-  使用 push_back():- 已有对象实例需添加时(代码意图更直观)。
- 传递右值时,若编译器能优化(如返回值优化),效率可能与 emplace_back接近。
 
4. 示例对比
// 定义一个类
class MyClass {
public:explicit MyClass(int a, int b) : a_(a), b_(b) {}
private:int a_, b_;
};std::vector<MyClass> v;// push_back 需要显式构造或转换:
v.push_back(MyClass(1, 2));    // 正确,但需构造临时对象
v.push_back({3, 4});            // 正确,C++11 统一初始化// emplace_back 直接传递参数:
v.emplace_back(5, 6);           // 直接构造,无临时对象
5. 注意事项
- 构造函数匹配:emplace_back可能因参数类型不明确导致意外调用构造函数。
- 异常安全:若构造过程中抛出异常,emplace_back可能使容器处于未定义状态(与push_back类似)。
总结
| 特性 | push_back() | emplace_back() | 
|---|---|---|
| 参数类型 | 对象实例(左值/右值) | 构造函数参数列表 | 
| 构造方式 | 拷贝或移动已有对象 | 直接在容器内存中构造 | 
| 效率 | 可能多一次拷贝/移动 | 通常更高效(省去临时对象) | 
| 适用场景 | 已有对象需添加时 | 直接构造、多参数、高开销对象、explicit 构造函数 | 
优先使用 emplace_back() 以提升性能,但在需要明确代码意图或已有对象时,push_back() 更直观。
