前言

最近看rocskdb源码,发现了大量的设计模式和C++高级特性,特此补充一下,巩固基础。

问题描述

其中关于动态数组的元素添加,代码中基本将push_back抛弃掉了,全部替换为emplace_back进行元素的添加。

看了一下官网描述:
原来的push_back 一个右值元素的时候 过程分为如下几步:

  • 使用右值数据类型的构造函数 构造一个临时对象
  • 调用拷贝构造函数将临时对象放入 容器中
  • 释放临时对象

可以看到以上的三个步骤,临时对象的资源就没有用到,而且还多了一次拷贝构造的过程,效率大大降低

后来真针对push_back的优化是引入了右值引用,即在构造出临时对象之后直接调用转移构造函数std::move()的形态,将临时对象的值和地址全部转移到容器,临时对象直接就变为空了。
所以c++11的emplace_back是在以上基础上进一步优化的,在容器的尾部添加元素,而这个元素是原地构造的,不需要调用拷贝构造函数和转移构造函数了。

测试

测试代码如下:

#include <iostream>
#include <vector>
#include <unistd.h>using namespace std;class Test {private:int num;public:Test(int x):num(x){std::cout << "constructed\n";}/*拷贝构造函数*/Test(const Test &obj) {num = obj.num;std::cout << "copy constructed\n";}/*C++11 支持的 转移构造函数*/Test (Test &&obj) {num = std::move(obj.num);std::cout << "moved constructed\n";}};int main() {vector<Test> arr;vector<Test> t_arr;std::cout << "push_back : Test(1)\n";arr.push_back(1);std::cout << "emplace_back : Test(1)\n";t_arr.emplace_back(1);return 0;
}

输出如下:

push_back : Test(1)
constructed
moved constructed
emplace_back : Test(1)
constructed

很明显,这里使用push_back进行了两次构造(临时对象的构造 和 转移构造函数),而empalce_back仅仅构造了临时对象。

所以emplace_back的性能会优于push_back。

源码分析

以下源码是boost库的最新源代码,所以push_back的实现也是经过优化的(将拷贝构造函数的实现变更为转移构造函数)
关于empalce_back的boost源码实现过程如下:

template <class _Tp, class _Allocator>
template <class... _Args>
inline
#if _LIBCPP_STD_VER > 14
typename vector<_Tp, _Allocator>::reference
#else
void
#endif
vector<_Tp, _Allocator>::emplace_back(_Args&&... __args)
{if (this->__end_ < this->__end_cap()){__RAII_IncreaseAnnotator __annotator(*this);/*传入可变长参数模版forward进行对象构造,并添加到this代表的容器的末尾*/__alloc_traits::construct(this->__alloc(),_VSTD::__to_raw_pointer(this->__end_),_VSTD::forward<_Args>(__args)...);__annotator.__done();++this->__end_;}else__emplace_back_slow_path(_VSTD::forward<_Args>(__args)...);
#if _LIBCPP_STD_VER > 14return this->back();
#endif
}

push_back的源码如下:

template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
void
vector<_Tp, _Allocator>::push_back(value_type&& __x)
{if (this->__end_ < this->__end_cap()){/*构造容器指针*/__RAII_IncreaseAnnotator __annotator(*this);/*使用move 的转移构造函数*/__alloc_traits::construct(this->__alloc(),_VSTD::__to_raw_pointer(this->__end_),_VSTD::move(__x));__annotator.__done();++this->__end_;}else__push_back_slow_path(_VSTD::move(__x));
}

C++ 中emplace_back和push_back差异相关推荐

  1. c++11中emplace_back vs push_back

    引言 在C11中,有两种方法可以把元素放入容器中:emplace_back和push_back. push_back是C11之前就有的,而emplace_back是C11中新加的. 既然它们的作用都是 ...

  2. C++11使用emplace_back代替push_back

    最近在写一段代码的时候,突然很好奇C++11中对push_back有没有什么改进以增加效率,上网搜了一些资料,发现果然新增了emplace_back方法,比push_back的效率要高很多. 首先,写 ...

  3. emplace_back和push_back对比分析

    emplace_back含义 emplace_back是C++11新引进的接口函数. emplace_back是就地构造,不用构造后再次复制到容器中.因此效率更高. push_back 简单的一个案例 ...

  4. C++11:右值引用、移动构造、std::move, 以及使用emplace_back代替push_back

    最近在写一段代码的时候,突然很好奇C++11中对push_back有没有什么改进以增加效率,上网搜了一些资料,发现果然新增了emplace_back方法,比push_back的效率要高很多. 1.右值 ...

  5. C++11:右值引用、move, 以及使用emplace_back代替push_back

    最近在写一段代码的时候,突然很好奇C++11中对push_back有没有什么改进以增加效率,上网搜了一些资料,发现果然新增了emplace_back方法,比push_back的效率要高很多. 1.右值 ...

  6. emplace_back与push_back异同

    vector的emplace_back与push_back 文章目录 vector的emplace_back与push_back 前言 1.区别总览 2.push_back 支持右值引用 不支持传入多 ...

  7. python2与python3性能对比_对Python2与Python3中__bool__方法的差异详解

    对Python2与Python3中__bool__方法的差异详解 发布时间:2020-08-28 00:08:58 来源:脚本之家 阅读:74 作者:grey_csdn 学习Python面向对象编程的 ...

  8. Linux和windows中的换行符差异问题 LINUX的换行符在Windows记事本打开不换行或出现黑点

    http://hi.baidu.com/mayongl7/blog/item/06e61af7c719053a730eec4d.html LINUX的换行符在Windows记事本打开不换行或出现黑点 ...

  9. ipv6协议与网络服务器有关,IPv6与IPv4协议网络中的双工通信差异

    我们都知道IPv6与IPv4协议网络的本质区别.那么在进行双向会话通信过程中两者有什么差异呢?下面我们就来详细说一下这方面的内容.Ipv6和IPv4协议动态NAT一样,NAT-PT只能用于由IPv6网 ...

最新文章

  1. 一图读懂HDFS--大数据平台技术栈06
  2. python的or操作符连接多个字符串含义是什么?
  3. linux驱动读取文件失败怎么办,linux – 由于单个驱动器读取错误导致软件RAID-1导致内核故障...
  4. 计算机操作系统笔记——处理器调度
  5. 【转】Unity3D将来时:IL2CPP(上)
  6. linux 更改mysql的数据库目录
  7. hadoop的开发工具_Hadoop开发工具简介
  8. python 遍历一个空列表
  9. #nginx# 泛解析大量域名的情况下 将不带www的域名,301到与之对应的www前缀的域名...
  10. jQuery基础(3)- ajax
  11. Win10如何开启IIS服务以及如何打开IIS管理器
  12. 计算机一级考试试题在线操作,计算机一级考试题库操作题
  13. 大学加权平均分计算器_澳大利亚移民宝藏专业----西澳大学幼教硕士解析
  14. 深入理解 http 反向代理(nginx)
  15. 快速入门github网站,了解GitHub网站的基本使用
  16. 自动驾驶中的SLAM
  17. 加油站都需要什么手续_企业自备加油站需要办理哪些手续
  18. iphone各机型的分辨率及像素
  19. 误检率、查准率、查全率、漏检率计算公式
  20. EOJ 唐纳德与子串 (Easy)

热门文章

  1. Jenkins实现SVN+Maven+Java项目的持续集成
  2. 学习笔记:腾讯云--域名解析
  3. 结构体成员的引用方法
  4. 全浏览器兼容的DIV拖动效果
  5. 如何 SQL Server 2005 实例之间传输登录和密码
  6. Codeforces Round #417:E. FountainsSagheer and Apple Tree(树上博弈)
  7. usaco Calf Flac(O(n)时间求回文串长度)
  8. python 修改计算机名_静心学数据分析002-python基础
  9. noip复赛普及组2020_我校学子在2020年“外研社·国才杯”全国英语写作大赛(高职组)复赛中斩获佳绩...
  10. linux vim6,VIM6:linux终端下的英文字典--SDCV