c++11 之emplace_back 与 push_back的区别

c++11 之emplace_back 与 push_back的区别c 开发中我们会经常用到插入操作对 stl 的各种容器进行操作 比如 vector map set 等 在引入右值引用 转移构造函数 转移复制运算符之前 通常使用 push back 向容器中加入一个右值元素 临时对象 时 首先会调用构造函数构造这个临时对象 然后需要调用拷贝构造函数将这个临时对象放入容器中 原来的临时变量释放 这样造成的问题就是临时变量申请资源的浪费 引入了右值引用 转移构造函数后

emplace_back函数原型:

template 
  
      void emplace_back (Args&&... args); 
  
#include 
  
    #include 
   
     #include 
    
      struct President { std::string name; std::string country; int year; President(std::string p_name, std::string p_country, int p_year) : name(std::move(p_name)), country(std::move(p_country)), year(p_year) { std::cout << "I am being constructed.\n"; } President(const President& other) : name(std::move(other.name)), country(std::move(other.country)), year(other.year) { std::cout << "I am being copy constructed.\n"; } President(President&& other) : name(std::move(other.name)), country(std::move(other.country)), year(other.year) { std::cout << "I am being moved.\n"; } President& operator=(const President& other); }; int main() { std::vector 
     
       elections; std::cout << "emplace_back:\n"; elections.emplace_back("Nelson Mandela", "South Africa", 1994); //没有类的创建 std::vector 
      
        reElections; std::cout << "\npush_back:\n"; reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936)); std::cout << "\nContents:\n"; for (President const& president: elections) { std::cout << president.name << " was elected president of " << president.country << " in " << president.year << ".\n"; } for (President const& president: reElections) { std::cout << president.name << " was re-elected president of " << president.country << " in " << president.year << ".\n"; } } 
       
      
     
    
  

输出

emplace_back: I am being constructed. push_back: I am being constructed. I am being moved. Contents: Nelson Mandela was elected president of South Africa in 1994. 

网上有人说尽量使用emplace_back代替 push_back 有没有什么特例是不能替换的呢,搜了一下发现了一个例子:

emplace_back造成的引用失效 

勘误:window visual studio 2015 编译下面程序会出现 引用失效问题,而linux gcc 和qt 等编译环境中未出现下面问题。感谢大家的指正。

#include 
  
    #include 
   
     #include 
    
      using namespace std; int main() { vector 
     
       ivec; ivec.emplace_back(1); ivec.emplace_back(ivec.back()); for (auto it = ivec.begin(); it != ivec.end(); ++it) cout << *it << " "; return 0; } //输出: 1 - 
      
     
    
  

尝试1:不直接给emplace_back传递ivec.back():

#include 
  
    #include 
   
     #include 
    
      using namespace std; int main() { vector 
     
       ivec; ivec.emplace_back(1); auto &it = ivec.back(); ivec.emplace_back(it); for (auto it = ivec.begin(); it != ivec.end(); ++it) cout << *it << " "; return 0; } 输出: 1 - 
      
     
    
  

尝试2:不给emplace_back传递引用:

#include 
  
    #include 
   
     #include 
    
      using namespace std; int main() { vector 
     
       ivec; ivec.emplace_back(1); auto it = ivec.back(); ivec.emplace_back(it); for (auto it = ivec.begin(); it != ivec.end(); ++it) cout << *it << " "; return 0; } 输出: 1 1 
      
     
    
  

我们如愿以偿,这时候应该可以得到结论了,ivec.back()返回的是引用,但是这个引用失效了,所以才会输出不正确;我们之前也提到过,重新分配内存会造成迭代器的失效,这里是造成了引用的失效。

#include 
  
    #include 
   
     #include 
    
      using namespace std; int main() { vector 
     
       ivec; ivec.reserve(4); ivec.emplace_back(1); ivec.emplace_back(ivec.back()); for (auto it = ivec.begin(); it != ivec.end(); ++it) cout << *it << " "; return 0; } 输出: 1 1 
      
     
    
  

参考链接:

https://blog.csdn.net/windpenguin/article/details/ 

https://blog.csdn.net/xiaolewennofollow/article/details/ 

https://blog.csdn.net/wangshubo1989/article/details/ 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/203034.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午10:44
下一篇 2026年3月19日 下午10:44


相关推荐

  • C多线程编程系列(三)- 线程同步

    C多线程编程系列(三)- 线程同步1 1 简介本章介绍在 C 中实现线程同步的几种方法 因为多个线程同时访问共享数据时 可能会造成共享数据的损坏 从而导致与预期的结果不相符 为了解决这个问题 所以需要用到线程同步 也被俗称为 加锁 但是加锁绝对不对提高性能 最多也就是不增不减 要实现性能不增不减还得靠高质量的同步源语 Synchronizat 但是因为正确永远比速度更重要 所以线程同步在某些场景下是必须的 线程同步有两种源语 Primitive 构造 用户模式 user mode 和内核模式 kern

    2026年3月16日
    2
  • eclipse导入jar包和源文件

    eclipse导入jar包和源文件当我们使用 eclipse 时 有时候需要导入 jar 包 源代码 和打包等 下面讲一下具体步骤 eclipse 导入 jar 包 源代码 打 jar 包等当我们使用 eclipse 时 有时候需要导入 jar 包 源代码 和打包等 下面讲一下具体步骤 1 首先下载需要的 jar 包 和源文件 2 创建一个 eclipse 工程 3 在工程目录下创建文件夹 libs4 将需要的 jar 包导入文件夹 libs

    2026年3月17日
    2
  • mysql报错注入_mysql报错注入[通俗易懂]

    mysql报错注入_mysql报错注入[通俗易懂]报错注入这里主要介绍3种MySQL数据库报错注入的发法,分别是updatexml、floor和exp。1.updatexmlupdatexml的报错原理从本质上来说就是函数的报错。selectupdatexml(1,concat(0x7e,(selectversion()),0x7e),1);这里还是使用前面的例子,举出一个爆破数据库版本的样例Payload:爆破数据库版本信息?id=1’+…

    2026年4月19日
    4
  • linux下安装mysql-5.7.25详细步骤

    linux下安装mysql-5.7.25详细步骤第一步:下载进入到mysql官网下载自己对应版本的mysql,下载地址:https://dev.mysql.com/downloads/mysql/5.7.html#downloads我这里下载mysql-5.7.25-linux-glibc2.12-x86_64.tar.gz版本也可以进入linux后用命令下载wgethttps://cdn.mysql.com/…

    2022年6月12日
    43
  • 彻底解决mysql报错:1030, ‘Got error 28 from storage engine‘

    彻底解决mysql报错:1030, ‘Got error 28 from storage engine‘恕我直言,网上文章千篇一律,没一个能解决的,全是说清一下内存就好了,但是并没有教不会的小白清理…==这个问题确实是服务器系统盘满了,mysql指定的临时文件目录满掉,大概就是这个意思.下面解决/dev/vda1系统盘满了,其实我压根不知道/dev/vda1这在哪,是什么,后来了解这是virtio-block类型的设备。科普一下:以’c’开头的一行表示该设备是一个……

    2022年10月21日
    4
  • 即梦ai动作模仿超过30秒怎么办

    即梦ai动作模仿超过30秒怎么办

    2026年3月12日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号