当前位置: 首页
编程语言
C++中push_back与emplace_back的区别

C++中push_back与emplace_back的区别

热心网友 时间:2026-06-11
转载

许多 C++ 开发者一直对 push_back()emplace_back() 的区别感到困惑:它们究竟有何不同?这次我直接查阅了 libstdc++ 的源代码,终于彻底理解了底层实现的本质差异。下面把我的核心发现分享出来,帮助大家在实际开发中做出更高效的选择。

C++中的push_back与emplace_back的区别?

  • allocate 源码:gcc.gnu.org/onlinedocs/…
  • push_back 实现:gcc.gnu.org/onlinedocs/…
  • emplace_back 实现:gcc.gnu.org/onlinedocs/…

先来看 push_back() 的工作流程。它要求传入一个已经构造好的对象(可以是左值或右值),然后在容器内部通过拷贝构造或移动构造来创建副本。换句话说,你传入一个临时对象,容器内部还需要再“复制”或“移动”一次,这就会多产生一次对象构造的开销。

// GCC libstdc++ vector
void push_back(const value_type& __x) {
    if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) {
        // 空间足够,在已开辟的内存上【拷贝构造】新对象
        this->_M_impl.construct(this->_M_impl._M_finish, __x);
        ++this->_M_impl._M_finish;
    } else {
        // 空间不足,扩容并移动/拷贝旧数据
        _M_realloc_insert(end(), __x);
    }
}void push_back(value_type&& __x) {
    if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) {
        // 空间足够,在已开辟的内存上【移动构造】新对象
        this->_M_impl.construct(this->_M_impl, this->_M_impl._M_finish, std::move(__x));
        ++this->_M_impl._M_finish;
    } else {
        _M_realloc_insert(end(), std::move(__x));
    }
}void 
construct(pointer __p, const _Tp& __val)  
{ ::new((void *)__p) _Tp(__val); }       /* 直接进行拷贝/移动构造 */

emplace_back() 走的则是完全不同的路径——它接收的不是已经构造好的对象,而是元素类型构造函数的参数。通过可变模板参数和完美转发机制,它直接在容器预留的内存上调用元素的构造函数,从而省去了创建临时对象再拷贝或移动的中间环节,在性能上更优。

template<typename... _Args>
void
emplace_back(_Args&&... __args) {
    if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) {
        // 空间足够,直接在目标内存上【就地构造】
        this->_M_impl.construct(this->_M_impl, this->_M_impl._M_finish,
                                 std::forward<_Args>(__args)...);
        ++this->_M_impl._M_finish;
    } else {
        _M_realloc_insert(end(), std::forward<_Args>(__args)...);
    }
}template<typename... _Args>              /* 可变模版参数 */ 
void
construct(pointer __p, _Args&&... __args)
{ ::new((void *)__p) _Tp(std::forward<_Args>(__args)...); } /* 完美转发 */

简单总结一下两者的核心区别:

  • 接口调用方式不同push_back() 接收的是已经构造好的对象(左值或右值引用),而 emplace_back() 接收的是元素类型的构造参数(理解起来可能有点绕,但掌握后非常直观)。
  • 底层实现机制不同push_back() 需要先在外层创建临时对象,再通过拷贝或移动构造将其“搬入”容器;emplace_back() 则直接在容器预留的内存上通过完美转发调用构造函数,完全省去了临时对象的创建与拷贝/移动步骤。对于复杂对象(如包含动态申请内存、资源管理的类型),这个性能差异非常明显,在 C++ 开发中值得优先考虑。
来源:https://juejin.cn/post/7648213611392434195

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
Linux环境下Node.js单元测试方法详解

Linux环境下Node.js单元测试方法详解

在Linux环境下对Node js项目进行单元测试,主流框架有Mocha、Jest和Jasmine。以Mocha为例,需先安装Node js与npm,创建package json,安装Mocha为开发依赖,建立test文件夹,编写测试用例,使用describe定义测试套件、it定义测试用例、assert断言。最后在scripts中添加test命令,通过npm

时间:2026-06-11 07:05
如何在Linux上全面管理Node.js依赖的实用步骤与技巧

如何在Linux上全面管理Node.js依赖的实用步骤与技巧

在Linux系统上,Node js依赖管理通过npm或Yarn进行,利用package json记录依赖,配合锁定文件确保版本一致。操作包括安装工具、初始化项目、安装生产与开发依赖、更新删除依赖、提交锁定文件、最小化依赖、安全审计及使用nvm管理Node js版本。

时间:2026-06-11 07:05
深入剖析Linux环境下ThinkPHP框架的安全风险及应对策略

深入剖析Linux环境下ThinkPHP框架的安全风险及应对策略

Linux环境下ThinkPHP安全取决于版本、配置与开发习惯。旧版存在preg_replace漏洞、控制器过滤不严及SQL注入风险;配置疏漏如开启调试模式、未强制路由等削弱防护。升级至6 x、关闭调试、禁用危险函数、开启强制路由、使用ORM、限制文件上传、配置防火墙与HTTPS可有效提升安全性。框架、系统、开发三位一体方能构建可靠防护。

时间:2026-06-11 07:05
Linux下JavaScript性能优化高效实现

Linux下JavaScript性能优化高效实现

在Linux环境下,JavaScript性能优化需从运行时环境、代码写法、并发处理、缓存策略、数据库优化、网络优化、监控分析、安全部署及代码分割等多环节进行迭代改进,持续精准解决性能瓶颈。

时间:2026-06-11 07:05
全面详解Node.js在Linux系统中的安全性保障与最佳实践

全面详解Node.js在Linux系统中的安全性保障与最佳实践

在Linux环境部署Node js应用,需从系统内核加固、服务精简、依赖审计、HTTPS加密、输入验证、权限分离、敏感信息管理及监控应急响应等多个环节进行系统安全防护,构建纵深防御体系,保障应用安全运行,确保系统稳健可靠。

时间:2026-06-11 07:05
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜