--------《深入应用C++11:代码优化与工程级应用》第2章使用C++11改进程序性能,本章将分别介绍右值引用相关的新特性。本节为大家介绍emplace_back减少内存拷贝和移动。---------

2.4 emplace_back减少内存拷贝和移动

emplace_back能就地通过参数构造对象,不需要拷贝或者移动内存,相比push_back能更好地避免内存的拷贝与移动,使容器插入元素的性能得到进一步提升。在大多数情况下应该优先使用emplace_back来代替push_back。所有的标准库容器(array除外,因为它的长度不可改变,不能插入元素)都增加了类似的方法:emplace、emplace_hint、emplace_front、emplace_after和 emplace_back,关于它们的具体用法可以参考cppreference.com。这里仅列举典型的示例。

vector的emplace_back的基本用法如下:
 

可以看出,emplace_back的用法比较简单,直接通过构造函数的参数就可以构造对象,因此,也要求对象有对应的构造函数,如果没有对应的构造函数,编译器会报错。如果把上面的构造函数注释掉,在vs2013下编译会报如下错误:
 error C2661: “A::A”: 没有重载函数接受 2 个参数

其他容器相应的emplace方法也是类似的。

相对push_back而言,emplace_back更具性能优势。下面通过一个例子来看emplace_back和push_back的性能差异,如代码清单2-5所示。

代码清单2-5 emplace_back和push_back的比较

#include <vector>
#include <map>
#include <string>
#include <iostream>
using namespace std; struct Complicated
{
int year;
double country;
std::string name; Complicated(int a, double b, string c):year(a),country(b),name(c)
{
cout<<"is constucted"<<endl;
} Complicated(const Complicated&other):year(other.year),country(other.country),name(std::move(other.name))
{
cout<<"is moved"<<endl;
}
}; int main()
{
std::map<int, Complicated> m;
int anInt = 4;
double aDouble = 5.0;
std::string aString = "C++";
cout<<"—insert--"<<endl;
m.insert(std::make_pair(4, Complicated(anInt, aDouble, aString))); cout<<"—emplace--"<<endl;
// should be easier for the optimizer
m.emplace(4, Complicated(anInt, aDouble, aString)); cout<<"--emplace_back--"<<endl;
vector<Complicated> v;
v.emplace_back(anInt, aDouble, aString);
cout<<"--push_back--"<<endl;
v.push_back(Complicated(anInt, aDouble, aString));
}

输出如下:

代码清单2-5测试了map的emplace和vector的emplace_back,用map的insert方法插入元素时有两次内存移动,而用emplace时只有一次内存移动;用vector的push_back插入元素时有两次移动内存,而用emplace_back时没有内存移动,是直接构造的。

可以看到,emplace/emplace_back的性能比之前的insert和push_back的性能要提高很多,我们应该尽量用emplace/emplace_back来代替原来的插入元素的接口以提高性能。需要注意的是,我们还不能完全用emplace_back来取代push_back等老接口,因为在某些场景下并不能直接使用emplace来进行就地构造,比如,当结构体中没有提供相应的构造函数时就不能用emplace了,这时就只能用push_back。

另外可参考:STL vector中的emplace_back方法

emplace_back减少内存拷贝和移动的更多相关文章

  1. C++11如何减少内存拷贝次数

    C++11中出现了很多迷人的特性.例如智能指针实现高效的内存管理,std::bind和std::function函数封装器,以及lambda实现的函数对象语法糖,都是使我着迷的地方. 而C++11最大 ...

  2. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  3. Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  4. python 变量作用域 v.__sizeof__() python 深复制 一切皆对象 尽量减少内存消耗

    python 深入理解 赋值.引用.拷贝.作用域 - 江召伟 - 博客园 https://www.cnblogs.com/jiangzhaowei/p/5740913.html a=[1,2,5]b= ...

  5. C# 处理应用程序减少内存占用

    SetProcessWorkingSetSize减少内存占用 系统启动起来以后,内存占用越来越大,使用析构函数.GC.Collect什么的也不见效果,后来查了好久,找到了个办法,就是使用 SetPro ...

  6. LeetCode-Repeated DNA Sequences (位图算法减少内存)

    Repeated DNA Sequences All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, ...

  7. 教你50招提升ASP.NET性能(九):显式的使用using语句减少内存泄露

    (15)Reduce memory leaks dramatically with the “using” statement 招数15: 显式的使用using语句减少内存泄露 If a type i ...

  8. memcpy内存拷贝及优化策略图解

    一般内存拷贝与优化 代码实现 #include<iostream> usingnamespace std; //不安全的内存拷贝(当源内存地址与目标内存地址重叠时会产生错误) void h ...

  9. Android有效的治疗方法Bitmap,减少内存

    Android有效的治疗方法Bitmap,减少内存 照片可能有不同的大小. 在很多情况下,大小.比如,我们的Camera应用,我们所拍的照片的大小远大于屏幕显示的大小 假如你的应用被限制了内存使用,显 ...

随机推荐

  1. ios UI实现技巧

    statusBar 移动位置 NSString *key = [[NSString alloc] initWithData:[NSData dataWithBytes:(unsigned ] enco ...

  2. 【翻译】Sencha Touch2.4 The Layout System 布局

    [翻译]The Layout System 布局 In Sencha Touch there are two basic building blocks: componentsand containe ...

  3. css之margin && padding讲解

    margin && padding盒子模型: margin是模块与模块的空隙,padding是内容与边框的空隙 注: 1.margin:边缘.空白 2.padding:填充 margi ...

  4. Sqli-labs less 26a

    Less-26a 这关与26的区别在于,sql语句添加了一个括号,同时在sql语句执行抛出错误后并不在前台页面输出.所有我们排除报错注入,这里依旧是利用union注入. sql语句为SELECT * ...

  5. javascript的Function 和其 Arguments

    http://shengren-wang.iteye.com/blog/1343256 javascript的Function属性:1.Arguments对象2.caller 对调用单前函数的Func ...

  6. Webpack+React配合开发

    前面两篇关于webpack的基础和进阶,请先务必阅读之前的文章. Webpack教程一 Webpack教程二 什么是React React是一个由Facebook开发的library,它的口号是“A ...

  7. JS事件驱动机制

    还记得当初学JAVA-GUI编程时学习过事件监听机制,此时再学习JavaScript中的事件驱动机制,不免简单.当初学习时也是画过原理图,所以从原理图开始吧! js是采用事件驱动(event-driv ...

  8. 浅说Java中的反射机制(二)

    写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...

  9. Edius 安装 looks插件整理

    需要安装looks插件到指定目录,在后面桥接时选择该目录. 包括安装looksbuilder插件.

  10. Spark源码分析(三)-TaskScheduler创建

    原创文章,转载请注明: 转载自http://www.cnblogs.com/tovin/p/3879151.html 在SparkContext创建过程中会调用createTaskScheduler函 ...