c++ emplace_back 和push_back使用对比,笔记

部署运行你感兴趣的模型镜像

如果对象已经存在,那么使用emplaceback 和pushback是一样的。
且都会调用拷贝构造

auto a = A(1)
a.emplace_back(a); 

如果对象是临时对象,都会进行临时构建,并且使用都使用移动构造函数再构建一次,也是一样

a.emplace_back(A(1)); 

如果直接给参数
那么pushback会临时构造对象并且使用移动构造到vector中
emplaceback会直接构建,只会构建一次。且如果只使用参数构造,pushback只能接受1个参数隐士构造,emplceback接受多个构造参数显示构造,意味着如果你需要通过多个参数构造对象,似乎只能使用emplaceback。

a.emplace_back(1,2,3);  // 可
a.push_back(1,2,3);  //编译不通过
a.push_back(1); // 可

所以,对于自定义资源型对象,那么要好好实现移动构造,编译器会优化到移动构造,需要你自己高效的实现

总结,c++ emplaceback 的语义可以翻译为原地构造,传一个已经存在的和pushback一样,并且都是拷贝。如果确定是亡值,手动使用stdmove可以触发移动构造,此时两者都一样
pushback似乎总是会进行两次构造

如果已经存在,使用push
如果直接用参数构建,使用emplace

最后贴一个tongyiqianwen的图,对比了一下,看起来它比gpt3.5(都回答错了)靠谱很多,看起来说得也是对的,需自行考究。
在这里插入图片描述

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

### emplace_backpush_back 的差异 在 C++ 中,`emplace_back` `push_back` 都是用于向容器(如 `vector`、`deque` 等)的末尾添加新元素的方法。然而,它们在实现机制性能上存在一些关键差异。 #### 构造方式的不同 - `push_back` 是通过复制或移动构造函数来添加元素。如果传递的是一个已经存在的对象,则会调用复制构造函数;如果传递的是一个临时对象,则可能会调用移动构造函数。 - `emplace_back` 则直接在容器内部的内存中构造新元素。它接受任意数量的参数,并将这些参数完美转发给构造函数,从而避免了不必要的拷贝或移动操作。 例如,在以下代码中: ```cpp std::vector<A> a; A obj(0); a.emplace_back(obj); // 调用了复制构造函数 ``` 与 ```cpp std::vector<A> a; A obj(1); a.push_back(obj); // 同样调用了复制构造函数 ``` 两者的输出结果相同,都显示了构造析构的过程。尽管如此,`emplace_back` 在某些情况下可以更高效地构造对象[^2]。 #### 性能上的优化 由于 `emplace_back` 允许直接在容器管理的内存空间中构造对象,这通常意味着它可以减少一次临时对象的创建以及随后的复制或移动操作。这对于那些具有复杂构造逻辑的对象来说尤其重要,因为它能够显著提升性能。 #### 异常安全性 - `emplace_back` 提供了更强的异常安全保证。如果在插入过程中抛出异常,容器的状态不会发生改变[^3]。 - 相比之下,`push_back` 如果在其内部需要重新分配内存时抛出了异常,那么原有的元素可能已经被移动,导致数据丢失的风险。 #### 使用场景 - 当你需要将一个已有的对象添加到容器中时,使用 `push_back` 更加直观且易于理解。 - 如果你希望利用完美转发特性,在容器内直接构造对象以提高效率,尤其是在处理大型对象或者频繁插入操作时,应该选择 `emplace_back`。 #### 示例代码 下面是一个简单的例子,展示了如何使用 `emplace_back` 来添加整数到 `deque` 容器中: ```cpp #include <deque> #include <iostream> int main() { std::deque<int> mydeque; mydeque.emplace_back(1); mydeque.emplace_back(2); mydeque.emplace_back(3); mydeque.emplace_back(4); mydeque.emplace_back(5); mydeque.emplace_back(6); for (auto it = mydeque.begin(); it != mydeque.end(); ++it) std::cout << ' ' << *it; return 0; } ``` 此程序将输出:`1 2 3 4 5 6`[^3]。 综上所述,虽然 `push_back` `emplace_back` 都能完成向容器尾部添加元素的任务,但在具体应用时应根据实际需求进行选择。当对性能有较高要求并且可以直接构造对象时,推荐使用 `emplace_back`;而在其他大多数情况下,`push_back` 依然是简单而有效的选择。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值