当前位置: 首页 > news >正文

emplace_back与push_back异同

vector的emplace_back与push_back

文章目录

  • vector的emplace_back与push_back
    • 前言
    • 1.区别总览
    • 2.push_back
      • 支持右值引用
      • 不支持传入多个构造参数
      • 总是会进行拷贝构造
    • 3.emplace_back
      • emplace_back可以接受`多个构造参数`
      • 支持原地构造

前言

 在vector中,通过push_backemplace_back都可以向尾部添加元素,用push_back也可以,用emplace_back也可以,只看最终造成的结果的话,似乎没有什么不同。我们总是能听到有人说emplace_back比push_back要,但是快在哪里呢? 什么情况下都快吗? 我们一起来跟着例子看一下。

1.区别总览

push_backemplace_back
是否支持右值引用支持支持
是否一定会发生拷贝构造一定不一定
是够支持直接传入多个构造参数支持一个构造参数支持多个构造参数
是够支持原地构造不支持支持

 下面对这些特性分别进行分析

2.push_back

支持右值引用

 印象中,push_back是不支持右值引用的,然而实际上,push_back一样支持右值引用,比如我们看push_back的源码

      voidpush_back(value_type&& __x){ emplace_back(std::move(__x)); }template<typename... _Args>

 又或者我们通过代码测试一下

    std::string s1 = "hello";vector<std::string> strVec;strVec.push_back(std::move(s1));cout<<"s1="<<s1<<endl;cout << "strVec.size=" << strVec.size()<<endl;cout << "strVec[0]=" << strVec[0] << endl;

控制台输出

s1=
strVec.size=1
strVec[0]=hello

 std::move将s1从一个左值转化为一个右值引用,传入到push_back作为参数,push_back接收了该参数并调用了std::string移动拷造函数,将资源转移到了容器内。这里提到了一个概念叫移动构造函数,下面会专门介绍这个概念。

不支持传入多个构造参数

 如果只需要传入一个构造参数就能构造对象 ,那么,可以直接在push_back传入这个构造参数,完成对象的构造,例如

class testClass{public:int m_a;int m_b;testClass(int a){m_a = a;m_b = 10;}testClass(int a, int b ){m_a = a;m_b = b;}
};
void testContruct(){vector<testClass> list;list.push_back(1);cout<<"list.size="<<list.size()<<endl;cout << "list[0].m_a=" << list[0].m_a << " list[0].m_b=" << list[0].m_b << endl;
}

 执行结果

list.size=1
list[0].m_a=1 list[0].m_b=10

 在只需要一个参数就能构造的情况下,push_back可以接受这个构造参数并调用相应构造方法进行构造。

 如果构造时需要多个构造参数,则只能手动构造一个临时对象,否则编译出错,例如

void testContruct(){//编译错误list.push_back(1,2);
}

 需要这样写

void testContruct(){list.push_back(testClass(1,2));cout << "list.size=" << list.size() << endl;cout << "list[0].m_a=" << list[0].m_a << " list[0].m_b=" << list[0].m_b << endl;s
}

 程序输出

list.size=1
list[0].m_a=1 list[0].m_b=2

 这里与emplace_back是不同的,emplace_back可以接受多构造参数的情况,下面会分析到。

总是会进行拷贝构造

 这点怎么理解呢,我们通过一个例子来感受一下

 首先创建一个类,实现其构造拷贝构造以及析构函数

class BaseClassTwoPara {public:BaseClassTwoPara(int a){m_a = a;m_b = 999;cout << "construct " << m_a << " " << m_b << endl;}BaseClassTwoPara(int a, int b){m_a = a;m_b = b;cout << "construct " << m_a << " " << m_b << endl;}BaseClassTwoPara(const BaseClassTwoPara &rhs){m_a = rhs.m_a;m_b = rhs.m_b;cout << "copy construct " << m_a << " " << m_b << endl;}~BaseClassTwoPara(){cout << "delete " << m_a << " " << m_b << endl;}int m_a, m_b;
};

 然后,创建一个vector,进行测试,分4种情况,

  • 传入一个构造参数,让push_back自己构造对象
void test_TwoPara_push_back_cp()
{vector<BaseClassTwoPara> vl;cout << "test_TwoPara_push_back_cp"<<endl;vl.push_back(888);
}

 控制台输出:

construct 888 999
copy construct 888 999
delete 888 999
test_TwoPara_push_back_cp
delete 888 999

 能看到,emplace_back首先调用BaseClassTwoPara的构造函数,构造一个临时对象,然后调用拷贝构造函数,将这个对象复制到容器中,然后立马析构掉临时对象,程序结束时,析构掉容器内的对象。

 所以,传入一个参数时,是会发生拷贝

  • 传入已经构造好的对象

 向vl中传入一个已经构造好的对象,观察输出

void test_TwoPara_push_back_cp()
{vector<BaseClassTwoPara> vl;BaseClassTwoPara b1(1, 2);vl.push_back(b1);cout << "test_TwoPara_push_back_cp" << endl;
}

 控制台输出

construct 1 2
copy construct 1 2
test_TwoPara_push_back_cp
delete 1 2
delete 1 2

 这里的流程是,b1首先调用两参数的构造函数,构造出一个局部对象,然后将这个对象作为push_back参数传入,v1复制b1对象到容器内,但是不会向上面那个例子那样,把b1析构,因为b1不是临时对象,程序退出时,b1以及vl内的对象被析构。

 所以,传入一个构造好的对象时,push_back会发生拷贝。

  • 传入一个临时对象

 通过BaseClassTwoPara(1,2)构造一个临时对象传入push_back

void test_TwoPara_push_back_cp()
{vector<BaseClassTwoPara> vl;vl.push_back(BaseClassTwoPara(1,2));cout << "test_TwoPara_push_back_cp" << endl;
}

 控制台输出:

construct 1 2
copy construct 1 2
delete 1 2
test_TwoPara_push_back_cp
delete 1 2

 可以看到,临时对象通过构造函数被创建后,vl复制该临时对象,然后析构临时对象,程序结束时,再析构容器内的对象,类似于上面提到的"传入一个构造参数,让push_back自己构造对象"这种情况。

 所以,传入一个临时对象,push_back会发生拷贝。

  • 传右值

 传右值时,会调用BaseClassTwoPara的移动构造函数,其实也是一种拷贝形式,这里会出现两种不同的情况

 (1)当传入一个右值时,v1首先调用普通构构造函数,构造一个BaseClassTwoPara临时对象,然后调用移动构造函数,在容器内构造一个对象,然后析构临时对象,可以下面代码看出。

void test_TwoPara_push_back_cp()
{vector<BaseClassTwoPara> vl;vl.push_back(1);cout << "test_TwoPara_push_back_cp" << endl;
}

 控制台输出

construct 1 999
move copy construct 1 999
delete 0 0
test_TwoPara_push_back_cp
delete 1 999

 (2)当传入一个右值引用时,直接调用移动构造函数,在容器中创建对象

void test_TwoPara_push_back_cp()
{vector<BaseClassTwoPara> vl;BaseClassTwoPara b1(1, 2);vl.push_back(std::move(b1))cout << "test_TwoPara_push_back_cp" << endl;
}
construct 1 2
move copy construct 1 2
test_TwoPara_push_back_cp
delete 0 0
delete 1 2

 所以,不论什么情况,push_back至少发生一次拷贝操作,这里说的拷贝也把移动构造算进来了,因为移动构造也是基于一个已有的对象,来创建一个新的对象。

3.emplace_back

 emplace_back的大部分特性与push_back都是一样的,这一小节只分析不同点。

 两点不同:

emplace_back可以接受多个构造参数

 可以将多个构造参数传入emplace_back,只要实现了对应的构造函数,就可以完成构造,例如

void test_TwoPara_push_back_cp()
{vector<BaseClassTwoPara> vl;vl.emplace_back(888,777);cout << "test_TwoPara_push_back_cp"<<endl;
}

 控制台输出

construct 888 777
test_TwoPara_push_back_cp
delete 888 777

 也就是emplace_back这里直接调用了BaseClassTwoPara两参数的构造函数,构造了一个BaseClassTwoPara对象,而push_back只能支持一个。

支持原地构造

 从上面👆这个测试的输出可以看出来,如果直接输入构造参数,emplace_back的表现与push_back完全不同,emplace_back直接将对象构造在了容器内,而不是构造一个临时的再拷贝到容器内,这点如果利用好了,可以大大提高性能。

以上就是emplace_back与push_back的异同点。

相关文章:

emplace_back与push_back异同

vector的emplace_back与push_back 文章目录vector的emplace_back与push_back前言1.区别总览2.push_back支持右值引用不支持传入多个构造参数总是会进行拷贝构造3.emplace_backemplace_back可以接受多个构造参数支持原地构造前言 在vector中&#xff0c;通过push_back与emplace_…...

【C语言航路】第十五站:程序环境和预处理

目录 一、程序的翻译环境和执行环境 二、编译和链接 1.翻译环境 2.编译本身也分为几个阶段 3.运行环境 三、预处理 1.预定义符号 2.#define 1.#define定义标识符 2.#define定义宏 3.#define 替换规则 4.#和## 5.带副作用的宏参数 6.宏和函数的对比 7.命名约定 …...

Vue3 - 获取 Proxy 对象代理中包裹的 “真实数据“,解决对象或数组打印后是 Proxy 对象无法拿到原始数据的问题(提供 2 种详细解决方案)

前言 在 Vue3 中很多数据都被 Proxy 代理对象 “包裹”(无法拿到其真正的原始数据),另外就是请求回来的数据,例如通过 res.data.data 拿到了一个数组对象格式的数据。但是这个数据被 Proxy 包裹,你根本拿不到值无法进行处理。 本文实现了 Vue3 取到被 proxy 对象包裹的原始…...

ESP32设备驱动-ML8511紫外线传感器驱动

ML8511紫外线传感器驱动 1、ML8511介绍 ML8511 是一款紫外线传感器,适用于室内或室外获取紫外线强度。 ML8511 配备了一个内部放大器,可根据紫外线强度将光电流转换为电压。 这种独特的功能提供了与 ADC 等外部电路的简单接口。 在掉电模式下,典型的待机电流为 0.1 μ \mu…...

SC12B触摸感应芯片评测方案(1)

MM32F0160SC12B Touch Application Evaluation 文章目录MM32F0160SC12B Touch Application EvaluationIntroduction & RequirementHardwareSC12B & SC12B Sample Demo boardMini-F0160 boardSoftwareMCU Software - MM32F0160PC Tool - FreeMASTERSummaryIntroduction …...

企业如何实现精细化人员管理?五大业务场景值得关注

近年来&#xff0c;随着大数据、人工智能和云计算等信息技术不断升级与渗透&#xff0c;处在数字化变革的劳动力密集型企业希望利用更加智能化的劳动力管理软件&#xff0c;帮助企业实现规范化的管理。 面对企业劳动力管理理念的变化&#xff0c;以及数字化转型的发展渗透&…...

C/C++每日一练(20230301)

目录 1. 冒泡排序法排序 ★ 2. 有效的数独 ★★ 3. 不同的二叉搜索树 II ★★ 附录 二叉搜索树 1. 冒泡排序法排序 输入n&#xff08;1≤n≤10&#xff09;个整数&#xff0c;用冒泡排序法对其从小到大排序&#xff0c;共进行n-1趟&#xff0c;要求输出每一趟的排序情…...

Vue项目中components组件的使用笔记

目录 前言 一、components和component的区别&#xff1f; 二、components使用的步骤 1.创建组件vue文件 2.引入组件 3.注册组件 4.应用组件 总结 前言 本文章&#xff0c;只是初步了解记录components的使用步骤。 一、components和component的区别&#xff1f; compo…...

2023软件测试行情不行了?

一、2023年软件测试行业的现状 2020年开年&#xff0c;一不小心&#xff0c;【新冠】黑天鹅从头上飘过&#xff0c;持续影响全国乃至全球的经济&#xff0c;软件行业公司也迎来了不少的冲击&#xff0c;那么一个值得打算入行软件测试行业&#xff0c;或者已经在软件测试行业耕耘…...

【java web篇】数据库连接池Driud的使用

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…...

无损音乐格式:FLAC和ALAC

前言&#xff1a;我最近在弄苹果的airplay项目&#xff0c;发现airplay2对比airplay多了音质方面的增强。AAC和MP3接触过&#xff0c;但对FLAC和ALAC完全不了解&#xff0c;整理学习资料汇总成如下信息&#xff1a; AirPlay2 在2017年推出&#xff0c;在前一代AirPlay的基础上…...

第十届蓝桥杯省赛——4质数(质数判断,数学函数:开方函数)

题目&#xff1a;试题 D: 质数本题总分&#xff1a;10 分【问题描述】我们知道第一个质数是 2、第二个质数是 3、第三个质数是 5……请你计算第 2019 个质数是多少&#xff1f;【答案提交】这是一道结果填空的题&#xff0c;你只需要算出结果后提交即可。本题的结果为一个整数&…...

MASKGROUP: HIERARCHICAL POINT GROUPING AND MASKING FOR 3D INSTANCE SEGMENTATION

ABSTRACT 本文研究了 3D 实例分割问题,该问题在机器人技术和增强现实等现实世界中具有多种应用。由于3D物体的周围环境非常复杂,不同物体的分离非常困难。为了解决这个具有挑战性的问题,我们提出了一个新的框架来对 3D 实例进行分组和优化。在实践中,我们首先为每个点学习…...

为什么地图可视化炙手可热?

我们在谈到数据可视化的时候&#xff0c;可能第一反应就是中间有一个地图样式的大屏图。但有没有想过&#xff0c;为什么大多数的可视化大屏中间都是一张地图的样子&#xff1f;这张地图样式的模块究竟是什么呢&#xff1f;它又是怎么做出来的&#xff1f; 其实这张地图样式的…...

JAVA代码审计篇-SQL注入

JAVA代码审计篇-SQL注入1、SQL注入漏洞简介2、SQL注入的条件3、审计方法4、JAVA中执行SQL的几种方式&#xff08;1&#xff09;使用JDBC的java.sql.Statement执行SQL语句&#xff08;2&#xff09;使用JDBC的java.sql.PreparedStatement执行SQL语句&#xff08;3&#xff09;使…...

SpringBoot接口传参方式

常见GET请求和POST请求的区别1.get请求无消息体&#xff0c;只能携带少量数据&#xff0c;且不安全post请求有消息体&#xff0c;可以携带大量数据&#xff0c;且安全2.携带数据的方式&#xff1a;get请求将数据放在url地址中post请求将数据放在消息体body中传参方式get方式---…...

高通平台开发系列讲解(Sensor篇)AlsPs的工作原理及介绍

文章目录 一、什么是ALS?二、什么是距感(PS)?三、AlsPs的工作原理四、AlsPs的特性五、距感的校准参数说明六、光感的校准参数说明沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇文章将介绍 AlsPs 的工作原理及介绍。 一、什么是ALS? 光感的英文叫做Ambient Li…...

集群方式下的java Redis锁 lua脚本

下面说一下集群方式redis 下的原子锁 带超时时间java 代码如下&#xff1a;List<String> keys Collections.singletonList("test_key1");System.out.println("打印前 &#xff1a;&#xff1a;"jedisCluster.get("test_key1"));//获取lua …...

【钓鱼实测】写bug给new bing和chatGPT查。问他们林黛玉倒拔垂杨柳

BUG 错误代码 #include <iostream> #include <vector> using namespace std; int main() {vector<int> vec{1,2,3,2,4};for (auto iter vec.begin(); iter ! vec.end(); iter ){if (*iter 2) {vec.erase(iter);}}cout << vec.size() << endl…...

基于OMAPL138+FPGA核心板多核软件开发组件MCSDK开发入门(上)

本文测试板卡为创龙科技 SOM-TL138F 是一款基于 TI OMAP-L138(定点/浮点 DSP C674x + ARM9)+ 紫光同创 Logos/Xilinx Spartan-6 低功耗 FPGA 处理器设计的工业级核心板。核心板内部OMAP-L138 与 Logos/Spartan-6 通过 uPP、EMIFA、I2C 通信总线连接,并通过工业级 B2B连接器引…...

C#/.net程序调用python

C#/.net程序调用python C#的优势在于window下的开发&#xff0c;不仅功能强大而且开发周期短。而python则有众多的第三方库&#xff0c;可以避免自己造轮子&#xff0c;利用C#来做界面&#xff0c;而具体实现使用python来实现可以大大提高开发效率。本文介绍如何使用pythonnet…...

一文讲清楚如何进行主数据编码

主数据编码作为一类重要的数据资源&#xff0c;在信息化建设中具有重要的地位和作用&#xff0c;是保证现有信息系统和未来新系统建设成功的关键因素&#xff0c;决定着系统中的信息一致性。 编码&#xff0c;是一件简单的事情&#xff0c;但绝对不是一件容易做好的事情&#…...

SAP 详解ST02

问&#xff1a;在st02中看到&#xff0c;Program和Export/Import的Swap出现红的了&#xff0c;这个是什么原因啊&#xff0c;是不是对系统的性能有影响啊&#xff0c;是否应该调整一些参数啊。要怎么调整呢&#xff1f; 复1&#xff1a;双击红色的部分就可以看到相应的参数修改…...

Go程序当父进程被kill,子进程也自动退出的问题记录

平常我们启动一个后台进程&#xff0c;会通过nouhp &的方式启动&#xff0c;这样可以在退出终端会话的时候&#xff0c;进程仍然可以继续在后台执行(进程的父进程id会从原来的bash进程变成1) 在go程序中&#xff0c;通过nouhp &的方式启动子进程&#xff0c;预期是即使…...

window10 下使用docmer-compose使用mysql镜像部署mysql

1. 在wins中找到store&#xff0c;安装Debian 2. 在桌面右键点击 linux shell窗口 3. 安装docker 4. 启动docker&#xff1a; service docker start 5. 配置加速器&#xff0c;为了拉取镜像更快&#xff0c;修改后得重新启动docker&#xff1a; vi /etc/docker/daemon.json…...

软件测试补充

软件开发的生命周期&#xff1a;需求-计划-设计-开发编码-测试-运行维护-上线 那我们的微信APP来进行举例: 需求:我需要你们团队做这样一个社交软件&#xff0c;能够像QQ一样实现聊天功能&#xff0c;发布说说的功能&#xff0c;能够群聊&#xff0c;可以转账 计划:计划软件…...

【算法】Tire字符串

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法篇 &#x1f43e;或许会很慢&#xff0c;但是不可以停下&#x1f43e; 文章目录1.Trie的基本思想1.1什么是Trie1.2字符串条件1.3如何存储字符串1.4如何查找字符串2.Trie的代码实现2.1怎么用数组建树2.2完整代码1.Trie的基本思…...

【C++】STL——list的模拟实现

list的模拟实现 文章目录list的模拟实现一、list三个基本类的模拟实现总览二、节点类接口实现模拟实现构造函数三、迭代器类接口实现1.正向迭代器默认成员函数构造函数六种运算符重载 */->//--/!/2.反向迭代器四、list类接口实现1.默认成员函数1.1.构造函数1.2.析构函数1.3.…...

SpringBoot小区物业管理系统

文章目录 项目介绍主要功能截图:后台登录车位收费管理物业收费管理投诉信息管理保修信息管理基础信息管理数据分析部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获…...

外网跨网远程控制内网计算机3种方案

远程控制&#xff0c;通俗来讲就是在自己个人电脑直接远程访问另台主机电脑桌面操作。 如何远程控制电脑&#xff1f;远程控制别人计算机的方案通常有两种&#xff0c;一种是开启电脑系统自带的远程桌面功能&#xff0c;如果涉及跨网内、外网互通可以同时用快解析内网映射外网&…...

福建自适应网站建设/北京seo案例

当我们去github上克隆代码仓库的时候&#xff0c;一般有两种选择&#xff0c;一种是https协议&#xff0c;一种是ssh协议。这也是最常用的两种协议了。 HTTPS协议&#xff08;推荐&#xff09; 优点&#xff1a; 对新手友好&#xff0c;使用简单&#xff0c;clone的时候只需…...

用什么软件做购物网站/太原网站关键词排名

在执行Hadoop的创建目录、写数据等情况&#xff0c;可能会出现该异常&#xff0c;而在读文件的时候却不会报错&#xff0c;这主要是由于系统的用户名不同导致的&#xff0c;由于我们进行实际开发的时候都是用Windows操作系统&#xff0c;而编译后的JAVA程序是部署在Linux上的。…...

怎么在b2b网站上发信息让百度收录怎么做/软件公司

本人出自&#xff1a;http://www.myexception.cn/android/558502.html listview滑动最后停止&#xff0c;没有执行onScrollStateChanged方法&#xff0c;最后停在onScroll&#xff0c;为什么啊&#xff1f; 场景是这样的&#xff1a;滑动列表快到最底部时&#xff0c;松开触摸…...

网站开发用了哪些知识要点/aso搜索优化

由于OpenCV中的直方图统计函数的实现过于复杂&#xff0c;所以本人就动手重写了直方图统计函数&#xff0c;与各位看官们分享交流一下&#xff01;当然了&#xff0c;代码还是基于OpenCV实现的。本人只实现了计算CV_8U类图像的直方图统计&#xff0c;从一维&#xff0c;二维&am…...

山东省住房和城乡建设厅网站/推广普通话手抄报内容50字

昆腾公司(NYSE:QTM)近期公布了截至2013年12月31日的2014财年第三财季的初步业绩。公司预计本财季的收入在1.45亿至1.46亿美元之间&#xff0c;高于2013年10月23日发布的业绩中预测的最高值。这要特别归功于Scalar磁带自动化系统和DXi重复数据删除设备销售收入的持续增长&#x…...

网站你的后台管理系统用什么做/职业培训热门行业

在突发大量内存的请求期间&#xff0c;哪些工具或最佳实践可用于在Java服务中正常降级服务&#xff1f; 有问题的应用程序是多线程的。 处理每个请求所需的工作量可能相差很大&#xff0c;并且不容易拆分和并行化。我很担心编写与堆使用和GC有关的应用程序级代码&#xff0c;但…...