简介
一直说, emplace_back 比 push_back 快, 我不信, 哈哈~~
参考链接
https://blog.csdn.net/yockie/article/details/52674366
https://www.zhihu.com/question/64493068
移动构造函数
using emplace_back avoids the extra copy or move operation required when using push_back(简单来说确实避免了移动构造函数.)
移动构造函数是C++11带来的std::move强制将左值转为右值, 简单来说就是, 你有一个指针对象, 当使用拷贝构造函数的时候, 消耗太大, 你可以只用移动构造函数, 将指针进行浅拷贝, 然后,就可以了, 这样带来性能的极大提高.
code
线上完整代码
#include <vector>
#include <string>
#include "time.hh"
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); //预分配十万大小,排除掉分配内存的时间
const int num = 100;
{
TIME_INTERVAL_SCOPE("push_back T:");
Foo temp("ceshi645231");
for(int i=0; i<num; i++) {
v.push_back(temp);// push_back(const T&),参数是左值引用
}
//打印结果:
//constructor
//copy constructor
}
std::cout << "111111111111111111111\n";
v.clear();
{
TIME_INTERVAL_SCOPE("push_back move(T):");
Foo temp("ceshi645321");
for(int i=0; i<num; i++) {
v.push_back(std::move(temp));// push_back(T &&), 参数是右值引用
}
//打印结果:
//constructor
//move constructor
}
std::cout << "222222222222222222222\n";
v.clear();
{
TIME_INTERVAL_SCOPE("push_back(T&&):");
for(int i=0; i<num; i++) {
v.push_back(Foo("ceshi654321"));// push_back(T &&), 参数是右值引用
}
//打印结果:
//constructor
//move constructor
}
std::cout << "333333333333333333333\n";
v.clear();
{
std::string temp = "ceshi123456";
TIME_INTERVAL_SCOPE("push_back(string):");
for(int i=0; i<num; i++) {
v.push_back(temp);// push_back(T &&), 参数是右值引用
}
//打印结果:
//constructor
//move constructor
}
std::cout << "444444444444444444444444444\n";
v.clear();
{
std::string temp = "ceshi123465";
TIME_INTERVAL_SCOPE("emplace_back(string):");
for(int i=0; i<num; i++) {
v.emplace_back(temp);// 只有一次构造函数,不调用拷贝构造函数,速度最快
}
//打印结果:
//constructor
}
}
#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)
测试结果
constructor
copy constructor
...
copy constructor
push_back T:922 ms
111111111111111111111
constructor
move constructor
...
move constructor
push_back move(T):893 ms
222222222222222222222
constructor
move constructor
constructor
...
constructor
move constructor
constructor
move constructor
push_back(T&&):1794 ms
333333333333333333333
constructor
move constructor
...
move constructor
constructor
move constructor
push_back(string):1884 ms
444444444444444444444444444
constructor
...
constructor
emplace_back(string):933 ms
---------------------------我的天空里没有太阳,总是黑夜,但并不暗,因为有东西代替了太阳。虽然没有太阳那么明亮,但对我来说已经足够。凭借着这份光,我便能把黑夜当成白天。我从来就没有太阳,所以不怕失去。
--------《白夜行》