C++的vector中emplace_back() 与 push_back() 的区别

C++ 中 vectoremplace_back()push_back() 均用于向容器末尾添加元素,但二者在实现和效率上有显著区别:

1. 参数传递方式

  • push_back() :接受一个已构造的对象(左值或右值),将其拷贝或移动到容器中。

    cpp 复制代码
    std::vector<MyClass> v;
    MyClass obj(1, 2);
    v.push_back(obj);             // 拷贝构造
    v.push_back(MyClass(3, 4));   // 移动构造(临时对象是右值)
  • emplace_back() :接受构造对象所需的参数列表,直接在容器内存中构造对象,无需临时对象。

    cpp 复制代码
    v.emplace_back(1, 2);         // 直接调用 MyClass(int, int)

2. 效率对比

  • push_back() 的潜在开销:

    • 若传递右值(如临时对象),会触发一次移动构造。
    • 若传递左值,会触发一次拷贝构造。
    • 需要先构造临时对象,再将其转移至容器。
  • emplace_back() 的优势:

    • 直接在容器内存中构造对象,省去临时对象的创建和转移步骤,尤其对拷贝/移动成本高的对象(如大型类)效率更优。

3. 适用场景

  • 优先使用 emplace_back()

    • 构造对象需要多个参数时,避免创建临时对象。
    • 对象拷贝/移动成本高时。
    • 需调用 explicit 构造函数时(emplace_back 支持直接初始化)。
  • 使用 push_back()

    • 已有对象实例需添加时(代码意图更直观)。
    • 传递右值时,若编译器能优化(如返回值优化),效率可能与 emplace_back 接近。

4. 示例对比

cpp 复制代码
// 定义一个类
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() 更直观。

相关推荐
lsx20240611 分钟前
传输对象模式
开发语言
ch.ju14 分钟前
Java Programming Chapter 4——Member method
java·开发语言
艾莉丝努力练剑16 分钟前
【Linux网络】Linux 网络编程:HTTP(五)HTTP收尾,从Cookie会话保持、抓包问题到 HTTPS 初识
linux·运维·服务器·网络·c++
Shadow(⊙o⊙)17 分钟前
前缀和:和可被K整除的子数组(normal)
数据结构·c++·算法
笨蛋不要掉眼泪17 分钟前
Java并发编程:ReentrantLock与AQS原理剖析
java·开发语言·并发
念何架构之路23 分钟前
Go依赖管理
开发语言·后端·golang
liudanzhengxi24 分钟前
CUDA转OpenCL:跨平台内核迁移实战
开发语言
吃好睡好便好27 分钟前
用if…elseif…end语句输出成绩等级
开发语言·前端·javascript·数据库·学习·matlab·信息可视化
努力努力再努力wz28 分钟前
【Redis入门系列】:Redis 内部编码机制与 String 深度解析:SDS 底层实现、三种编码与核心命令详解
c语言·开发语言·数据结构·数据库·c++·redis·缓存
必胜刻29 分钟前
Go 调用Coze工作流实现 AI 游戏生成
开发语言·ai·golang·gin