【C++】C++11 STL容器emplace方法原理剖析
在 C++ 11 STL 容器中,push/insert => emplace 新的方法,push 和 emplace 的区别在于:
1. push
push 通常用于将一个元素添加到容器的末尾(在 std::vector、std::deque 等序列容器中),或者在关联容器中插入一个键值对(如 std::map 或 std::set)。
std::vector<int> vec;
vec.push_back(10); // 将 10 添加到 vector 的末尾
对于关联容器(如 std::map),push 可能是 insert 的一种实现:
std::map<int, std::string> m;
m.insert({1, "one"}); // 插入键值对
2. emplace
emplace 是 C++11 引入的一个新方法。它的主要优点是在容器中直接构造元素,而不是先构造好对象再将其插入到容器中。这可以避免不必要的复制或移动操作,从而提高效率。
std::vector<int> vec;
vec.emplace_back(10); // 直接在 vector 的末尾构造 10
对于 std::map 或 std::set,emplace 会通过传递构造函数的参数直接构造元素(键值对),避免了额外的复制或移动操作:
std::map<int, std::string> m;
m.emplace(1, "one"); // 直接在 map 中构造键值对
主要区别:
-
元素构造方式:
push:需要先构造元素,然后将它添加到容器中。emplace:直接在容器内部构造元素,避免了额外的拷贝或移动。
-
性能:
emplace在某些情况下可以比push更高效,因为它避免了不必要的临时对象创建和拷贝。- 对于简单类型(如
int),这两者差别不大,但对于复杂类型,emplace可能会带来性能上的优势。
-
使用的场景:
push更常见于将已有对象添加到容器中,尤其是当元素类型比较简单时。emplace更适合在容器中直接构造复杂对象,尤其是在对象构造涉及多个参数时。
总结:
push是将已经构造好的元素添加到容器中。emplace是直接在容器中构造元素,避免了多余的复制或移动,通常能带来更好的性能。
在需要频繁插入复杂对象时,emplace 通常是更优选择。
代码验证:
class Test
{
public:Test(int a){std::cout << "Test(int)" << std::endl;}Test(int a, int b){std::cout << "Test(int, int)" << std::endl;}Test(const Test& t){std::cout << "Test(const Test&)" << std::endl;}Test(Test&& t){std::cout << "Test(Test&&)" << std::endl;}
};int main()
{Test t1(10);std::vector<Test> v;v.reserve(100);std::cout << "==========================" << std::endl;// 直接插入对象,两个是没有区别的v.push_back(t1);v.emplace_back(t1);std::cout << "==========================" << std::endl;// 直接插入对象,两个是没有区别的v.push_back(Test(20));v.emplace_back(Test(20));std::cout << "==========================" << std::endl;// 给emplace传入Test对象构造所需的参数,直接在容器中进行构建即可v.emplace_back(20);v.emplace_back(30, 40);
}
emplace 代码实现:
// 实现容器的空间配置器
template<typename T>
struct MyAllocator
{T* allocate(size_t size){return (T*)malloc(size * sizeof(T));}template<typename... Types>void construct(T* ptr, Types&&... args){new (ptr) T(args...);}
};template<typename T, typename Alloc = MyAllocator<T>>
class vector
{
public:vector(): m_vec(nullptr), m_size(0), m_idx(0){}// 预留内存空间void reserve(size_t size){m_vec = m_allocator.allocate(size);m_size = size;}// push_backvoid push_back(const T& val){m_allocator.construct(m_vec + m_idx, val);idx++;}void push_back(T&& val){m_allocator.construct(m_vec + m_idx, std::move(val));idx++;}template<typename... Types>void emplace_back(Types&&... args){m_allocator.construct(m_vec + m_idx, std::forward<Types>(args)...);m_idx++;}private:T* m_vec;int m_size;int m_idx;Alloc m_allocator;
};
相关文章:
【C++】C++11 STL容器emplace方法原理剖析
在 C 11 STL 容器中,push/insert > emplace 新的方法,push 和 emplace 的区别在于: 1. push push 通常用于将一个元素添加到容器的末尾(在 std::vector、std::deque 等序列容器中),或者在关联容器中插入…...
QT-简单视觉框架代码
文章目录 简介1. 整体架构2. 关键类功能概述3. 详细代码实现hikcameraworker.h 和 hikcameraworker.cpp(海康相机工作线程类)imageviewerwidget.h 和 imageviewerwidget.cpp(图像查看部件类)构造函数 ImageViewerWidget析构函数 ~…...
AI新书推荐:深度学习和大模型原理与实践(清华社)
本书简介 在这个信息爆炸、技术革新日新月异的时代,深度学习作为人工智能领域的重要分支,正引领着新一轮的技术革命。《深度学习和大模型原理与实践》一书,旨在为读者提供深度学习及其大模型技术的全面知识和实践应用的指南。 本书特色在于…...
[spring]处理器
我们可以通过spring来管理我们的类,之后我们可以通过spring的容器来获取我们所需要的Bean类对象。Spring的处理器是Spring对外开发的重要扩展点,它允许我们介入到Bean的整个实例化流程中来,可以动态添加、修改BeanDefinition、动态修改Bean 首…...
重温设计模式--中介者模式
中介者模式介绍 定义:中介者模式是一种行为设计模式,它通过引入一个中介者对象来封装一系列对象之间的交互。中介者使得各个对象之间不需要显式地相互引用,从而降低了它们之间的耦合度,并且可以更方便地对它们的交互进行管理和协调…...
重温设计模式--设计模式七大原则
文章目录 1、开闭原则(Open - Closed Principle,OCP)定义:示例:好处: 2、里氏替换原则(Liskov Substitution Principle,LSP)定义:示例:好处&#…...
LeetCode429周赛T4
最小化二进制字符串中最长相同子字符串的长度 在处理二进制字符串问题时,优化字符串结构以满足特定条件是一项常见的挑战。本文将探讨一个具体的问题:给定一个长度为 n 的二进制字符串 s 和一个整数 numOps,通过最多 numOps 次位翻转操作&am…...
详解MySQL在Windows上的安装
目录 查看电脑上是否安装了MySQL 下载安装MySQL 打开MySQL官网,找到DOWNLOADS 然后往下翻,找到MySQL Community(GPL) Downloads>> 然后找到MySQL Community Server 然后下载,选择No thanks,just start my download. 然后双击进行…...
【Python使用】嘿马python高级进阶全体系教程第10篇:静态Web服务器-返回固定页面数据,1. 开发自己的静态Web服务器【附代码文档】
本教程的知识点为:操作系统 1. 常见的操作系统 4. 小结 ls命令选项 2. 小结 mkdir和rm命令选项 1. mkdir命令选项 压缩和解压缩命令 1. 压缩格式的介绍 2. tar命令及选项的使用 3. zip和unzip命令及选项的使用 4. 小结 编辑器 vim 1. vim 的介绍 2. vim 的工作模式 …...
软件测试面试题和简历模板(面试前准备篇)
一、问题预测 1、让简单介绍下自己(这个不用说了每次面试开场) 面试官,你好,我叫xxx,xx年本科毕业,从事软件测试将近3年的时间。在此期间做过一些项目也积累过一些经验,能够独立地完成软件测试…...
Linux 基本使用和程序部署
1. Linux 环境搭建 1.1 环境搭建方式 主要有 4 种: 直接安装在物理机上。但是Linux桌面使用起来非常不友好,所以不建议。[不推荐]。使用虚拟机软件,将Linux搭建在虚拟机上。但是由于当前的虚拟机软件(如VMWare之类的)存在一些bugÿ…...
uniapp微信小程序,使用fastadmin完成一个一键获取微信手机号的功能
前端部分 点击按钮,获取手机号 <button open-type"getPhoneNumber" getphonenumber"bindGetPhoneNumber" hover-class"none"class"btn-purity">一键获取</button> 传入openid和code bindGetPhoneNumber(e) …...
CSS系列(27)- 图形与滤镜详解
前端技术探索系列:CSS 图形与滤镜详解 🎨 致读者:探索CSS的艺术表现力 👋 前端开发者们, 今天我们将深入探讨 CSS 图形和滤镜效果,学习如何创建引人注目的视觉效果。 基础图形 🚀 几何形状…...
Docker 技术系列之安装多版本Mysql5.6和Mysql5.7
image 大家好,后面的就不是关于MAC专有的内容,基本是跟Java环境,基础技术方面有关。所以这个教程对于在linux系统还是macOS都是通用的,不用担心。 上一篇,我们安装好对应的Docker之后,感受到了它的便利。接…...
理解并使用Linux 内核中的 Tracepoint
理解并使用Linux 内核中的 Tracepoint 1. 引言 1.1 为什么需要 Tracepoint? 在内核调试与性能分析中,传统的 printk 方法虽然简单直接,但存在几个显著的局限性: 日志噪音:printk 会将所有输出无差别地记录到系统日…...
centos7中Gbase8s数据库安装,以及数据导入遇到的一系列问题
centos7中Gbase8s数据库安装,以及遇到的一系列问题 以下是我在centos7上安装gbase8s数据库遇到的一系列问题,包括数据库安装,数据导入,数据连接,不能完全作为标准,只可作为类似问题参考,有问题…...
AW36518芯片手册解读(3)
接前一篇文章:AW36518芯片手册解读(2) 二、详述 3. 功能描述 (1)上电复位 当电源电压VIN降至预定义电压VPOR(典型值为2.0V)以下时,该设备会产生复位信号以执行上电复位操作&#x…...
MySQL的REPEATABLE READ事务隔离级别
本文隔离级别: T1内读T2的update数据 首先开两个事务(左二) 事务1修改成李四,提交 事务2再读还是张三,也就是说,记录的数据从事务开始时一直到结束,读的都是同一个版本,读不到T2未提交的此条记录修改&…...
sqoop的参数有哪些?
Sqoop 是一款用于在 Hadoop 与关系型数据库之间进行数据传输的工具,它有很多参数,可分为通用参数、导入参数和导出参数等,以下是一些常见的参数介绍: 通用参数 --connect 说明:指定要连接的关系型数据库的 JDBC URL。…...
动态规划<四> 回文串问题(含对应LeetcodeOJ题)
目录 引例 其余经典OJ题 1.第一题 2.第二题 3.第三题 4.第四题 5.第五题 引例 OJ 传送门Leetcode<647>回文子串 画图分析: 使用动态规划解决 原理:能够将所有子串是否是回文的信息保存在dp表中 在使用暴力方法枚举出所有子串,是…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
