STL中push_back和emplace_back效率的对比


我们以STL中的vector容器为例。我们来看看这两个函数的原型:

在这里插入图片描述
在这里插入图片描述

然后我们用一段代码来看看执行这两个函数时的过程:

#include<iostream>
#include <vector>
using namespace std;

class MyTest
{
public:
    //普通构造
    MyTest(int id,int age):m_id(id),m_age(age)
    { 
        cout << "ceate MyTest class..." << this << endl;
    }
    //拷贝构造
    MyTest(const MyTest &t):m_id(t.m_id),m_age(t.m_age)
    {  
        cout << "copy construct called..." << this << endl;
    }
    //移动构造
    MyTest(const MyTest &&t)
    {
        m_id = std::move(t.m_id);
        m_age = std::move(t.m_age);
        cout << "move contruct called.." << this << endl;
    }
    //析构
    ~MyTest()
    {
        cout << "destory MyTest class..." << this << endl;
    }
private:
    int m_id; //id成员
    int m_age;//age成员
};

过程对比

首先我们先总结它们的效率对比

  • 内置类型(built-in type):都一样
  • 用户自定义的类(User-defined type):emplace_pack仅在通过使用 构造参数 传入 的时候更高效!

1.通过构造参数向vector中插入对象(emplace_back更高效)

在这里插入图片描述

2.通过插入实例对象(调用copy函数)

在这里插入图片描述

3.通过插入临时对象(调用move函数)

在这里插入图片描述

效率对比

同样是在容器尾部增加一个元素,emplace_back 比 push_back 少了一次对象的构造和析构, 所以,emplace_back 比 push_back 更高效, 具体能高效多少呢,这里进行了一个插入 一百万 个对象的测试,emplace_back 比 push_back 快大概 20% ,下面是测试代码 :

//获取当前时间,单位: 毫秒
int64_t cur_msec()
{
    struct timespec tp1;
    clock_gettime(CLOCK_REALTIME, &tp1);
    return (tp1.tv_sec * 1000 + (int64_t)tp1.tv_nsec / 1000000.0);
}
//测试函数
void test()
{
    vector<MyTest> vec1;
    vector<MyTest> vec2;
    vec1.reserve(1000000);
    vec2.reserve(1000000);

    int64_t t1 = cur_msec();
    for (size_t i = 0; i < 1000000; i++)
    {
        vec1.push_back(MyTest(1,20));
    }
    int64_t t2 = cur_msec();
    for (size_t i = 0; i < 1000000; i++)
    {
        vec2.emplace_back(1,20);
    }
    int64_t t3 = cur_msec();
    
   cout << " push_back cost " << (t2 - t1) << " millisecond " << endl;
   cout << " emplace_back cost " << (t3 - t2) << " millisecond " << endl;
}

emplace_back 的缺点

既然 emplace_back 比 push_back 更高效,是不是每次都用 emplace_back 就完了呢?

我们日常写代码,除了执行率之外,还要考虑可读性,理解成本等,虽然emplace_back 效率高些,但是它也是有缺点的,比如:

vec1.push_back(1000000);
vec2.emplace_back(1000000);

第一行程序代码很好理解,往 容器vec1尾部加入一个整数 1000000,然而,第二行程序代码就不是很直观了,由于我们不知道 vec2 的实际类型,所以无法获得这行代码执行的结果。

假如,vec2 的类型是 vector,那么它的含义和第一行一样,往容器vec2尾部添加整数 1000000。

假如,vec2 的类型是 vector< vector >,那么它就构造了一个包含 1000000 个元素的容器,按照每个元素 4 个字节来计算,执行第二行代码需要分配差不多近 4M 的内存空间。

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值