emplace_back在容器内直接构造对象,避免拷贝或移动;push_back需先构造再插入,可能触发拷贝或移动操作。

emplace_back 和 push_back 都用于向容器(如 vector)尾部添加元素,但它们在实现机制和性能上有重要区别。
构造方式不同
push_back 是将一个已经构造好的对象插入容器。如果传入的是临时值或右值,会触发移动构造;如果是左值,则调用拷贝构造。
emplace_back 则是在容器内部直接构造对象,通过完美转发将参数传递给元素类型的构造函数,在原地创建实例,避免了额外的拷贝或移动操作。
示例说明:
立即学习“C++免费学习笔记(深入)”;
假设有类 A:struct A { A(int x, int y) { /* 构造逻辑 */ } };
使用 push_back 需先构造再插入:A a(1, 2); vec.push_back(a); // 拷贝构造vec.push_back(A(3, 4)); // 移动构造(或 RVO 优化)
而 emplace_back 直接构造:vec.emplace_back(5, 6); // 原地构造,无需临时对象
性能对比
对于简单类型(如 int、double),两者性能差异极小,因为拷贝成本低。
对于复杂对象(尤其是没有移动构造或移动代价高的类型),emplace_back 通常更高效。
优势场景:
- 对象构造昂贵且参数简单时,emplace_back 减少一次临时对象的生成与析构
- 不支持移动语义的类型,push_back 只能拷贝,emplace_back 可原地构造
- 频繁插入大对象或资源管理类(如 string、unique_ptr)时,减少开销明显
注意点:
- emplace_back 参数必须匹配目标类型的构造函数,否则编译失败
- 某些情况下,编译器优化(如 RVO/NRVO)可消除 push_back 的临时对象,缩小差距
- emplace_back 可能引发异常时,容器状态仍安全,但构造中途失败可能导致未定义行为(取决于实现)
使用建议
多数现代 C++ 代码中推荐优先使用 emplace_back 插入非平凡对象,尤其当你只需传递参数而不持有实例。
若已有对象实例,push_back 更直观且无额外风险。
对性能敏感的场景,应结合 profiling 实测两种方式在具体类型上的表现。
基本上就这些。区别核心在于“先构造再拷贝” vs “原地构造”,性能差异取决于对象的构造/移动成本。









