vector的push_back v.s. emplace_back
vector的push_back v.s. emplace_back
正文
在 C++ 的 std::vector
中,emplace_back
和 push_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. 特殊情况与注意事项
-
隐式类型转换:
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)
-
性能陷阱:
- 若对象本身构造代价低(如内置类型
int
,double
),emplace_back
与push_back
性能差异可忽略。 - 对复杂对象(如包含动态内存的类),
emplace_back
通常更高效。
- 若对象本身构造代价低(如内置类型
-
异常安全性:
emplace_back
可能在构造过程中抛出异常,此时容器保持原状(强异常安全保证)。
总结
- 优先使用
emplace_back
:当需要直接通过参数构造对象时(尤其是对象构造成本高或不可拷贝/移动时)。 - 使用
push_back
:当已有对象或需要显式控制拷贝/移动行为时。
通过合理选择二者,可以显著优化代码性能并简化逻辑。
本文作者:Gold_stein
本文链接:https://www.cnblogs.com/smartljy/p/18702376
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下