STL中push_back和emplace_back效率的对比

文章目录

  • 过程对比
    • 1.通过构造参数向vector中插入对象(emplace_back更高效)
    • 2.通过插入实例对象(调用copy函数)
    • 3.通过插入临时对象(调用move函数)
  • 效率对比
  • 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 的内存空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/519857.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 刷题 [C++] 第300题.最长递增子序列

题目描述 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。 题目…

Leetcode 206. 反转链表

给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1] 示例 3&#xff1a; 输…

forwardRef和useImperativeHandle的配合使用

通过ref调用子组件里的方法 useImperativeHandle往外暴露子组件的方法&#xff0c;注意useImperativeHandle第三个参数中括号依赖&#xff0c;有这个依赖&#xff0c;childFun才能获取到最新的值

计算机基础专升本笔记十四-计算机网络基础(一)

计算机基础专升本笔记十四-计算机网络基础&#xff08;一&#xff09; 一、计算机网络的发展历程 第一代计算机网络&#xff08;数据通信&#xff09; 以数据通信为主的第一代计算机网络。主要是指美国军方用于防控系统的一种联机系统。它只是计算机网络的雏形。 第二代计算…

【思考】crud接口命名规范

写代码时取名字真的是痛苦。 方法命名 1、阿里命名规范 Service/Dao 层命名规约 1&#xff09; 获取单个对象的方法用 get 做前缀。 2&#xff09; 获取多个对象的方法用 list 做前缀。 3&#xff09; 获取统计值的方法用 count 做前缀。 4&#xff09; 插入的方法用 save&am…

20240304-使用VS2022编译blender3.6.2源代码

20240304-使用VS2022编译blender3.6.2源代码 一、软件环境 Win10 x64 22h2 JuneVS2022 v17.9.0CMake v3.24.4SVN v1.14.3GIT v2.29.2标签&#xff1a;win10 22h2 vs2022 blender 63335分栏&#xff1a;C 二、硬件环境 Win10 x64的PC台式机 三、获取源码 方法一 网盘下载…

粉色ui微信小程序源码/背景图/头像/壁纸小程序源码带流量主

云开发版粉色UI微信小程序源码&#xff0c;背景图、头像、壁纸小程序源码&#xff0c;带流量主功能。 云开发小程序源码无需服务器和域名即可搭建小程序另外还带有流量主功能噢&#xff01;微信平台注册小程序就可以了。 这套粉色UI非常的好看&#xff0c;里面保护有背景图、…

【框架学习 | 第二篇】暴打MyBatis-Plus——MyBatis的升级版本

教程来源链接&#xff1a;https://www.quanxiaoha.com/mybatis-plus/mybatis-plus-tutorial.html 教程作者&#xff1a;犬小哈 文章目录 1.Mybatis Plus介绍1.1Mybatis和Mybatis Plus的区别是什么1.1.1什么是Mybatis?1.1.2区分Mybatis Plus和Mybatis 1.2Mybatis Plus特点1.3支…

Vue3_2024_6天【回顾上篇watch常见的前三种场景】另两种待补

第一种情况&#xff1a;监视【ref】定义&#xff08;基本数据类型&#xff09; 1.引入watch2.格式&#xff1a;watch&#xff08;基本数据类型数据&#xff0c;监视变化的回调函数&#xff09; 注意点&#xff1a; 2.1.watch里面第一个参数&#xff0c;是数据~~【监视的基本类…

泛型 --java学习笔记

什么是泛型 定义类、接口、方法时&#xff0c;同时声明了一个或者多个类型变量&#xff08;如&#xff1a;<E>&#xff09;&#xff0c;称为泛型类、泛型接口&#xff0c;泛型方法、它们统称为泛型 可以理解为扑克牌中的癞子&#xff0c;给它什么类型它就是什么类型 如…

开篇语 | 容器中的⼤模型 (LLM in Containers)

如果我们想搭建一个企业级的大模型应用&#xff0c;不管使用开源的基础模型自己来发布&#xff0c;还是使用类似于 ChatGPT 的闭源 API&#xff0c;我们都需要搭建一个大模型流水线来管理应用体系中除了基础模型之外的功能模块。 Replit 的一篇博客&#xff08;https://blog.r…

鸿蒙ArkTS语言快速入门-TS(一)

ArkTS与TS的学习 ArkTS与TS的关系简述TypeScript&#xff08;TS&#xff09;简述基础类型1&#xff0c;let2&#xff0c;const3&#xff0c;布尔类型4&#xff0c;数字number5&#xff0c;字符串string6&#xff0c;数组Array7&#xff0c;元组 Tuple8&#xff0c;枚举 enum9&a…