vector的push_back v.s. emplace_back

vector的push_back v.s. emplace_back

正文

在 C++ 的 std::vector 中,emplace_backpush_back 都用于向容器末尾添加元素,但它们的实现方式和性能特点有明显差异。以下是两者的核心区别:


1. 参数传递与构造方式

方法 参数类型 构造行为
push_back 已构造的对象 接受一个对象,通过 拷贝或移动 到容器末尾。
emplace_back 构造参数(直接传递参数) 直接在容器内存中 原地构造对象,无需临时对象。

2. 性能差异

  • push_back

    • 若参数是临时对象(如右值),会触发 移动构造(如果对象可移动)。
    • 若参数是左值,会触发 拷贝构造
    • 示例:
      std::vector<MyClass> vec;
      MyClass obj(1, 2, 3);
      vec.push_back(obj);          // 拷贝构造
      vec.push_back(MyClass(4,5,6)); // 移动构造(临时对象)
      
  • emplace_back

    • 直接通过参数构造对象避免临时对象的创建,性能更优。
    • 示例:
      std::vector<MyClass> vec;
      vec.emplace_back(1, 2, 3); // 直接调用 MyClass(int, int, int) 构造函数
      

3. 适用场景

场景 推荐方法
添加已存在的对象(左值) push_back
添加临时对象(右值) push_back + std::move
直接构造对象(避免临时对象) emplace_back
对象不可拷贝/不可移动 必须用 emplace_back

4. 语法对比

// push_back:需要构造临时对象
vec.push_back(MyClass(a, b, c));

// emplace_back:直接传递构造参数
vec.emplace_back(a, b, c);

5. 特殊情况与注意事项

  1. 隐式类型转换

    • push_back 可能因类型不匹配而失败,而 emplace_back 允许隐式调用构造函数。
      struct MyClass {
          explicit MyClass(int x) {} // explicit 构造函数
      };
      
      std::vector<MyClass> vec;
      vec.push_back(10);    // 错误:不能隐式转换 int 到 MyClass
      vec.emplace_back(10); // 正确:直接调用 MyClass(int)
      
  2. 性能陷阱

    • 若对象本身构造代价低(如内置类型 int, double),emplace_backpush_back 性能差异可忽略。
    • 对复杂对象(如包含动态内存的类),emplace_back 通常更高效。
  3. 异常安全性

    • emplace_back 可能在构造过程中抛出异常,此时容器保持原状(强异常安全保证)。

总结

  • 优先使用 emplace_back:当需要直接通过参数构造对象时(尤其是对象构造成本高或不可拷贝/移动时)。
  • 使用 push_back:当已有对象或需要显式控制拷贝/移动行为时。

通过合理选择二者,可以显著优化代码性能并简化逻辑。

本文作者:Gold_stein

本文链接:https://www.cnblogs.com/smartljy/p/18702376

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Gold_stein  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑
  1. 1 逃离地面 RAD & 三浦透子
逃离地面 - RAD & 三浦透子
00:00 / 00:00
An audio error has occurred.

作词 : 野田洋次郎

作曲 : 野田洋次郎

空飛ぶ羽根と引き換えに 繋ぎ合う手を選んだ僕ら

それでも空に魅せられて 夢を重ねるのは罪か

夏は秋の背中を見て その顔を思い浮かべる

憧れなのか、恋なのか 叶わぬと知っていながら

重力が眠りにつく 1000年に一度の今日

太陽の死角に立ち 僕らこの星を出よう

彼が眼を覚ました時 連れ戻せない場所へ

「せーの」で大地を蹴って ここではない星へ

行こう

もう少しで運命の向こう もう少しで文明の向こう

もう少しで運命の向こう もう少しで

夢に僕らで帆を張って 来たるべき日のために夜を超え

いざ期待だけ満タンで あとはどうにかなるさと 肩を組んだ

怖くないわけない でも止まんない

ピンチの先回りしたって 僕らじゃしょうがない

僕らの恋が言う 声が言う

「行け」と言う