emplace_back VS push_back

简介

一直说, 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

emplace_back VS push_back

上一篇:17.面向对象程序设计入门——03(封装,继承,多态)


下一篇:Error Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 解决办法