C++11使用emplace_back代替push_back
最近在写一段代码的时候,突然很好奇C++11中对push_back有没有什么改进以增加效率,上网搜了一些资料,发现果然新增了emplace_back方法,比push_back的效率要高很多。
首先,写了一个类用于计时,
//time_interval.h
#pragma once
#include <iostream>
#include <memory>
#include <string>
#ifdef GCC
#include <sys/time.h>
#else
#include <ctime>
#endif // GCC
class TimeInterval
{
public:
TimeInterval(const std::string& d) : detail(d)
{
init();
}
TimeInterval()
{
init();
}
~TimeInterval()
{
#ifdef GCC
gettimeofday(&end, NULL);
std::cout << detail
<< 1000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / 1000
<< " ms" << endl;
#else
end = clock();
std::cout << detail
<< (double)(end - start) << " ms" << std::endl;
#endif // GCC
}
protected:
void init() {
#ifdef GCC
gettimeofday(&start, NULL);
#else
start = clock();
#endif // GCC
}
private:
std::string detail;
#ifdef GCC
timeval start, end;
#else
clock_t start, end;
#endif // GCC
};
#define TIME_INTERVAL_SCOPE(d) std::shared_ptr<TimeInterval> time_interval_scope_begin = std::make_shared<TimeInterval>(d)
使用方法就是在作用域中使用宏TIME_INTERVAL_SCOPE(d),d为打印用的字符串,输出作用域的耗时情况。
其次,看一下现在push到vector的5种方法的耗时情况对比:
#include <vector>
#include <string>
#include "time_interval.h"
int main() {
std::vector<std::string> v;
int count = 10000000;
v.reserve(count); //预分配十万大小,排除掉分配内存的时间
{
TIME_INTERVAL_SCOPE("push_back string:");
for (int i = 0; i < count; i++)
{
std::string temp("ceshi");
v.push_back(temp);// push_back(const string&),参数是左值引用
}
}
v.clear();
{
TIME_INTERVAL_SCOPE("push_back move(string):");
for (int i = 0; i < count; i++)
{
std::string temp("ceshi");
v.push_back(std::move(temp));// push_back(string &&), 参数是右值引用
}
}
v.clear();
{
TIME_INTERVAL_SCOPE("push_back(string):");
for (int i = 0; i < count; i++)
{
v.push_back(std::string("ceshi"));// push_back(string &&), 参数是右值引用
}
}
v.clear();
{
TIME_INTERVAL_SCOPE("push_back(c string):");
for (int i = 0; i < count; i++)
{
v.push_back("ceshi");// push_back(string &&), 参数是右值引用
}
}
v.clear();
{
TIME_INTERVAL_SCOPE("emplace_back(c string):");
for (int i = 0; i < count; i++)
{
v.emplace_back("ceshi");// 只有一次构造函数,不调用拷贝构造函数,速度最快
}
}
}
vs2015 release下编译,运行结果:
push_back string:327 ms
push_back move(string):213 ms
push_back(string):229 ms
push_back(c string):215 ms
emplace_back(c string):122 ms
第1中方法耗时最长,原因显而易见,将调用左值引用的push_back,且将会调用一次string的拷贝构造函数,比较耗时,这里的string还算很短的,如果很长的话,差异会更大
第2、3、4中方法耗时基本一样,参数为右值,将调用右值引用的push_back,故调用string的移动构造函数,移动构造函数耗时比拷贝构造函数少,因为不需要重新分配内存空间。
第5中方法耗时最少,因为emplace_back只调用构造函数,没有移动构造函数,也没有拷贝构造函数。
为了证实上述论断,我们自定义一个类,并在普通构造函数、拷贝构造函数、移动构造函数中打印相应描述:
#include <vector>
#include <string>
#include "time_interval.h"
class Foo {
public:
Foo(std::string str) : name(str) {
std::cout << "constructor" << std::endl;
}
Foo(const Foo& f) : name(f.name) {
std::cout << "copy constructor" << std::endl;
}
Foo(Foo&& f) : name(std::move(f.name)){
std::cout << "move constructor" << std::endl;
}
private:
std::string name;
};
int main() {
std::vector<Foo> v;
int count = 10000000;
v.reserve(count); //预分配十万大小,排除掉分配内存的时间
{
TIME_INTERVAL_SCOPE("push_back T:");
Foo temp("ceshi");
v.push_back(temp);// push_back(const T&),参数是左值引用
//打印结果:
//constructor
//copy constructor
}
v.clear();
{
TIME_INTERVAL_SCOPE("push_back move(T):");
Foo temp("ceshi");
v.push_back(std::move(temp));// push_back(T &&), 参数是右值引用
//打印结果:
//constructor
//move constructor
}
v.clear();
{
TIME_INTERVAL_SCOPE("push_back(T&&):");
v.push_back(Foo("ceshi"));// push_back(T &&), 参数是右值引用
//打印结果:
//constructor
//move constructor
}
v.clear();
{
std::string temp = "ceshi";
TIME_INTERVAL_SCOPE("push_back(string):");
v.push_back(temp);// push_back(T &&), 参数是右值引用
//打印结果:
//constructor
//move constructor
}
v.clear();
{
std::string temp = "ceshi";
TIME_INTERVAL_SCOPE("emplace_back(string):");
v.emplace_back(temp);// 只有一次构造函数,不调用拷贝构造函数,速度最快
//打印结果:
//constructor
}
}
结论:在C++11情况下,果断用emplace_back代替push_back
C++11使用emplace_back代替push_back的更多相关文章
- (转)C++11使用emplace_back代替push_back (其中有关于右值引用)
最近在写一段代码的时候,突然很好奇C++11中对push_back有没有什么改进以增加效率,上网搜了一些资料,发现果然新增了emplace_back方法,比push_back的效率要高很多. 首先,写 ...
- 学习 emplace_back() 和 push_back 的区别 emplace_back效率高
在引入右值引用,转移构造函数,转移复制运算符之前,通常使用push_back()向容器中加入一个右值元素(临时对象)的时候,首先会调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放 ...
- 编程杂谈——使用emplace_back取代push_back
近日在YouTube视频上看到关于vector中emplace_back与push_back区别的介绍,深感自己在现代C++中还是有不少遗漏的知识点,遂写了段代码,尝试比较两者的差别. 示例代码 #i ...
- C++11 vector使用emplace_back代替push_back
C++11中,针对顺序容器(如vector.deque.list),新标准引入了三个新成员:emplace_front.emplace和emplace_back,这些操作构造而不是拷贝元素.这些操作分 ...
- emplace_back与push_back的区别
std::vector::emplace_back C++ Containers library std::vector template< class... Args &g ...
- 【C/C++开发】emplace_back() 和 push_back 的区别
在引入右值引用,转移构造函数,转移复制运算符之前,通常使用push_back()向容器中加入一个右值元素(临时对象)的时候,首先会调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放 ...
- emplace_back() 和 push_back 的区别(转)
在引入右值引用,转移构造函数,转移复制运算符之前,通常使用push_back()向容器中加入一个右值元素(临时对象)的时候,首先会调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放 ...
- C++ std::vector emplace_back 优于 push_back 的理由
#include <iostream> #include <vector> #include <chrono> #include <windows.h> ...
- emplace_back() 和 push_back 的区别
在引入右值引用,转移构造函数,转移复制运算符之前,通常使用push_back()向容器中加入一个右值元素(临时对象)的时候,首先会调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放 ...
随机推荐
- python nose测试框架全面介绍七--日志相关
引: 之前使用nose框架时,一直使用--logging-config的log文件来生成日志,具体的log配置可见之前python nose测试框架全面介绍四. 但使用一段时间后,发出一个问题,生成的 ...
- 解决jenkins下使用HTML Publisher插件后查看html报告显示不正常
在jenkins后使用html publisher查看html报告时,发现显示不全,很多东西显示不了. 在查看官方文档后,这原来是安全问题所导致的. Jenkins安全默认是将以下功能都关闭了 1.j ...
- vue之用法
一.安装 对于新手来说,强烈建议大家使用<script>引入 二. 引入vue.js文件 我们能发现,引入vue.js文件之后,Vue被注册为一个全局的变量,它是一个构造函数. 三.使用V ...
- Centos清除IP
要把配置好的ip清除掉,可以使用以下命令: ip addr flush dev eth0 如果系统中没有ip这个命令,可以使用更简单的: ifconfig eth0 0.0.0.0 可以用于PPTP拨 ...
- zero-shor learning 数据集
OSR数据集下载地址: http://people.csail.mit.edu/torralba/code/spatialenvelope/ Relative Attributes Marr Priz ...
- gevent 真正的协程
import gevent #第一次使用需要cmd窗口敲入 pip install Gevent from gevent import monkey:monkey.patch_all import t ...
- 任何时候心中都要有WBS的模版树---产品模块级项目
- UVA 11768 - Lattice Point or Not
首先本题需要用到扩展欧几里得算法…… 关于exgcd算法的一点简略证明: 那么,对于函数exgcd(a,b)=(d,x,y),其中d满足d=gcd(a,b); (x,y)满足ax+by=d; 则exg ...
- 为什么面试要问 hashmap 的原理
我们都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如此特殊呢?是因为这道题考察的深度很深.这题经常出现在高级或中高级面试中.投资银行更喜欢问这个问题 ...
- tcpdump抓包二进制tcp协议详细分析
1.tcpdump -i eth0 port 11751 and src host 192.168.1.34 -x -s0 tcpdump: verbose output suppressed, us ...