emplace_back减少内存拷贝和移动
--------《深入应用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减少内存拷贝和移动的更多相关文章
- C++11如何减少内存拷贝次数
C++11中出现了很多迷人的特性.例如智能指针实现高效的内存管理,std::bind和std::function函数封装器,以及lambda实现的函数对象语法糖,都是使我着迷的地方. 而C++11最大 ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- python 变量作用域 v.__sizeof__() python 深复制 一切皆对象 尽量减少内存消耗
python 深入理解 赋值.引用.拷贝.作用域 - 江召伟 - 博客园 https://www.cnblogs.com/jiangzhaowei/p/5740913.html a=[1,2,5]b= ...
- C# 处理应用程序减少内存占用
SetProcessWorkingSetSize减少内存占用 系统启动起来以后,内存占用越来越大,使用析构函数.GC.Collect什么的也不见效果,后来查了好久,找到了个办法,就是使用 SetPro ...
- LeetCode-Repeated DNA Sequences (位图算法减少内存)
Repeated DNA Sequences All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, ...
- 教你50招提升ASP.NET性能(九):显式的使用using语句减少内存泄露
(15)Reduce memory leaks dramatically with the “using” statement 招数15: 显式的使用using语句减少内存泄露 If a type i ...
- memcpy内存拷贝及优化策略图解
一般内存拷贝与优化 代码实现 #include<iostream> usingnamespace std; //不安全的内存拷贝(当源内存地址与目标内存地址重叠时会产生错误) void h ...
- Android有效的治疗方法Bitmap,减少内存
Android有效的治疗方法Bitmap,减少内存 照片可能有不同的大小. 在很多情况下,大小.比如,我们的Camera应用,我们所拍的照片的大小远大于屏幕显示的大小 假如你的应用被限制了内存使用,显 ...
随机推荐
- Matlab计算矩阵和函数梯度
一.差分与微分 我自己的理解. 二.求解 2.1 矩阵 这就是matlab的计算结果.太小的话放大些: c = 4 5 9 7 2 1 5 2 6 >> [x,y]=gradient(c) ...
- Leetcode#152 Maximum Product Subarray
原题地址 简单动态规划,跟最大子串和类似. 一维状态空间可以经过压缩变成常数空间. 代码: int maxProduct(int A[], int n) { ) ; ]; ]; ]; ; i > ...
- 用DIV+CSS切割多背景合并图片 CSS Sprites 技术
很久之前就在互联网网站和一些js插件中见过这种技术的应用,当时觉得很麻烦,就没有用,也没有去深究. 近段时间一直在做前台的一些东西,涉及到很多div+css的问题.这个东东我又碰到了,所以我花了点时间 ...
- org.apache.kafka.common.network.Selector
org.apache.kafka.common.client.Selector实现了Selectable接口,用于提供符合Kafka网络通讯特点的异步的.非阻塞的.面向多个连接的网络I/O. 这些网络 ...
- C#与C++之间类型的对应{转}
Windows Data Type .NET Data Type BOOL, BOOLEAN Boolean or Int32 BSTR String BYTE Byte CHAR ...
- mybatis中:returned more than one row, where no more than one was expected.异常
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.ExecutorEx ...
- asp.net @reqister指令
@register指令通过声明将自定义 ASP.NET 服务器控件添加到页或用户控件中. 1.@register 指令有两种用法如下 <%@ Register tagprefix="t ...
- 11gR2数据库日志报错:Fatal NI connect error 12170、
11gR2数据库日志报错:Fatal NI connect error 12170.TNS-12535.TNS-00505 [问题点数:100分,结帖人MarkIII] 不显示 ...
- ab压力测试工具-批量压测脚本
ab(Apache benchmark)是一款常用的压力测试工具.简单易用,ab的命令行一次只能支持一次测试.如果想要批量执行不同的测试方式,并自动对指标进行分析,那么单靠手工一条一条命令运行ab,估 ...
- ZOJ 2588 Burning Bridges (tarjan求割边)
题目链接 题意 : N个点M条边,允许有重边,让你求出割边的数目以及每条割边的编号(编号是输入顺序从1到M). 思路 :tarjan求割边,对于除重边以为中生成树的边(u,v),若满足dfn[u] & ...