无用知识之:std::initializer_list的秘密
先说结论,用std::initializer_list初始化vector,内部逻辑是先生成了一个临时数组,进行了拷贝构造,然后用这个数组的起终指针初始化initializer_list。然后再用initializer_list对vector进行初始化,这个动作又触发了拷贝构造。
所以说,用initializer_list初始化,还是有优化空间的。
感觉吧,如果你真想用vector保存对象,减少一半的拷贝动作的方法:最好用vector的emplace_back把数据给move进去,或者原地初始化。
或者,就用vector保存指针
std::vector<std::string> vec1{ "ant", "bat", "cat" };
运行到initializer_list的构造函数:
D:\DevTools\VS2017\VC\Tools\MSVC\14.16.27023\include\initializer_listtemplate<class _Elem>class initializer_list{ // list of pointers to elements
public:typedef _Elem value_type;typedef const _Elem& reference;typedef const _Elem& const_reference;typedef size_t size_type;typedef const _Elem* iterator;typedef const _Elem* const_iterator;constexpr initializer_list() noexcept: _First(nullptr), _Last(nullptr){ // empty list}constexpr initializer_list(const _Elem *_First_arg,const _Elem *_Last_arg) noexcept: _First(_First_arg), _Last(_Last_arg){ // construct with pointers} //。。。。。。。。。。。。。。。。运行到这里。。。。。。。。。。。。。。..........};
这个std::initializer_list是怎么个事呢,它就是一个wrapper,一个viewer。注意它的构造函数,接收的是起始指针和末尾的指针。所以std::initializer_list就是保存了起终指针。所以std::initializer_list对象的拷贝,也是属于“浅拷贝”,保存的都是指针,不影响它们指向的数据。
下面的描述,说明了:
https://cplusplus.com/reference/initializer_list/initializer_list/
initializer_list objects are automatically constructed as if an array of elements of type T was allocated, with each of the elements in the list being copy-initialized to its corresponding element in the array, using any necessary non-narrowing implicit conversions.
The initializer_list object refers to the elements of this array without containing them: copying an initializer_list object produces another object referring to the same underlying elements, not to new copies of them (reference semantics).
The lifetime of this temporary array is the same as the initializer_list object.
通过这个了例子,说明了初始化initializer_list所用的起终指针,是来自于一个
“数组”,这个数组提前被拷贝构造函数初始化过了。相当于先进行了三次拷贝动作。class MyDate
{
public:MyDate()//构造函数{std::cout << "构造函数 this地址 " << this << std::endl;}~MyDate()//析构函数{std::cout << "析构函数" << std::endl;}MyDate(std::initializer_list<MyDate>& d)//initializer_list拷贝构造函数{std::cout << "initializer_list拷贝构造函数" << std::endl;}MyDate(const MyDate& d)//拷贝构造函数{std::cout << "/拷贝构造函数 scr地址 " << &d << std::endl;std::cout << "拷贝构造函数 this地址 " << this << std::endl;}MyDate& operator=(const MyDate& d)//赋值运算符重载{std::cout << "赋值运算符重载" << std::endl;return *this;}MyDate* operator&()//取地址运算符重载(&){std::cout << "取地址运算符重载(&)" << std::endl;return this;}const MyDate* operator&() const//const修饰的取地址运算符重载(const &){//std::cout << "const修饰的取地址运算符重载(const &)" << std::endl;return this;}int val;
};int main()
{
构造函数 this地址 000000000014F1C4MyDate d0; std::cout << "d0 already initialized" << std::endl;std::cout << std::endl;/拷贝构造函数 scr地址 000000000014F1C4 “看地址,说明用d0进行的初始化”
拷贝构造函数 this地址 000000000014F1E4MyDate d1{ d0};std::cout << "d1 already initialized" << std::endl;std::cout << std::endl;打印信息
//拷贝构造函数 scr000000000014F1C4 “看地址,说明用d0进行的初始化”
拷贝构造函数 this000000000014FDA8
/拷贝构造函数 scr000000000014F1C4 “看地址,说明用d0进行的初始化”
拷贝构造函数 this000000000014FDAC
/拷贝构造函数 scr000000000014F1C4 “看地址,说明用d0进行的初始化”
拷贝构造函数 this000000000014FDB0解释:
初始化了一个长度为3的“临时”数组,用d0进行了三次构造拷贝动作,数组中每个对象的地址分别为
000000000014FDA8
000000000014FDAC
000000000014FDB0紧接着打印:
/拷贝构造函数 scr地址 000000000014FDA8
拷贝构造函数 this地址 00000000005E3660
/拷贝构造函数 scr地址 000000000014FDAC
拷贝构造函数 this地址 00000000005E3664
/拷贝构造函数 scr地址 000000000014FDB0
拷贝构造函数 this地址 00000000005E3668解释:
这些打印信息,是把临时数组里的对象拷贝进了vector里:
vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc()): _Mybase(_Al){ // construct from initializer_list, optional allocator_Range_construct_or_tidy(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{});}std::vector < MyDate> d2{ d0,d0,d0 };//std::vector < MyDate> d2{ d0,d0,d0 };这段代码相当于:
//std::vector<MyDate> dt;
//dt.reserve(3);
//dt.emplace_back(d0);
//dt.emplace_back(d0);
//dt.emplace_back(d0);
//std::initializer_list lst(dt.begin(), dt.end());
//std::vector < MyDate> d2(lst); //对vector用initializer_list进行初始化return 1;
}

相关文章:
无用知识之:std::initializer_list的秘密
先说结论,用std::initializer_list初始化vector,内部逻辑是先生成了一个临时数组,进行了拷贝构造,然后用这个数组的起终指针初始化initializer_list。然后再用initializer_list对vector进行初始化,这个动作又触发了拷贝…...
论文阅读笔记 —— 英文论文常见缩写及含义
正文 缩写全称含义Reference发音w.r.twith reference to关于, 根据WRT - Wikiet al.拉丁语et alia的缩写等等Et Al. | Meaning & Use in APA, MLA & Chicago–etc拉丁语et cetera的缩写等等ETC - Cambridge DictionaryWhat’s ‘etc.’ an abbreviation of (and what …...
实验9 JSP访问数据库(二)
实验9 JSP访问数据库(二) 目的: 1、熟悉JDBC的数据库访问模式。 2、掌握预处理语句的使用 实验要求: 1、使用Tomcat作为Web服务器 2、通过JDBC访问数据库,实现增删改查功能的实现 3、要求提交实验报告,将代…...
[c语言日寄]C语言类型转换规则详解
【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…...
Airflow:选择合适执行器扩展任务执行
Apache Airflow是面向开发人员使用的,以编程方式编写、调度和监控的数据流程平台。可伸缩性是其关键特性之一,Airflow支持使用不同的执行器来执行任务。在本文中,我们将深入探讨如何利用这些执行器在Airflow中有效地扩展任务执行。 理解Airfl…...
使用冒泡排序模拟实现qsort函数
1.冒泡排序 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h>int main() {int arr[] { 0,2,5,3,4,8,9,7,6,1 };int sz sizeof(arr) / sizeof(arr[0]);//冒泡排序一共排序 sz-1 趟for (int i 0; i < sz - 1; i){//标志位,如果有序,直接…...
AI大模型开发原理篇-4:神经概率语言模型NPLM
神经概率语言模型(NPLM)概述 神经概率语言模型(Neural Probabilistic Language Model, NPLM) 是一种基于神经网络的语言建模方法,它将传统的语言模型和神经网络结合在一起,能够更好地捕捉语言中的复杂规律…...
Eigen::Tensor使用帮助
0 引言 用python实现了某些算法之后,想转成C来获取更高的性能。但是python数组的操作太灵活了,尤其是3维、4维、5维等高维数组,以及它们的广播、数组坐标、切片等机制。还有numpy的pad、where等操作更是给C转换带来了更多的麻烦。 查阅了相…...
git基础使用--3---git安装和基本使用
文章目录 git基础使用--3--git-安装和基本使用1. git工具安装1.1 git1.2 TortoiseGit1.3 远程仓2. git本地仓库版本管理2.1 git常用命令2.2 git基本操作2.2.1 设置用户名和邮箱 2.2 git基本操作2.2.1 初始化本地仓 git init2.2.2 查看本地库状态 git status2.2.3 添加暂缓区2.2…...
html的字符实体和颜色表示
在HTML中,颜色可以通过以下几种方式表示,以下是具体的示例: 1. 十六进制颜色代码 十六进制颜色代码以#开头,后面跟随6个字符,每两个字符分别表示红色、绿色和蓝色的强度。例如: • #FF0000:纯红…...
OpenAI发布o3-mini:免费推理模型,DeepSeek引发的反思
引言 在人工智能领域,OpenAI再次引领潮流,推出了全新的推理模型系列——o3-mini。这一系列包括low、medium和high三个版本,旨在进一步推动低成本推理的发展。与此同时,OpenAI的CEO奥特曼也在Reddit的“有问必答”活动中罕见地公开…...
Zemax 中带有体素探测器的激光谐振腔
激光谐振腔是激光系统的基本组成部分,在光的放大和相干激光辐射的产生中起着至关重要的作用。 激光腔由两个放置在光学谐振器两端的镜子组成。一个镜子反射率高(后镜),而另一个镜子部分透明(输出耦合器)。…...
大模型训练(5):Zero Redundancy Optimizer(ZeRO零冗余优化器)
0 英文缩写 Large Language Model(LLM)大型语言模型Data Parallelism(DP)数据并行Distributed Data Parallelism(DDP)分布式数据并行Zero Redundancy Optimizer(ZeRO)零冗余优化器 …...
C# 实现 “Hello World” 教程
.NET学习资料 .NET学习资料 .NET学习资料 C# 作为一种广泛应用于.NET 开发的编程语言,以其简洁、高效和类型安全等特性,深受开发者喜爱。在踏入 C# 编程领域时,编写经典的 “Hello World” 程序是重要的起点,它能帮助我们快速熟…...
LabVIEW无线齿轮监测系统
本案例介绍了基于LabVIEW的无线齿轮监测系统设计。该系统利用LabVIEW编程语言和改进的天牛须算法优化支持向量机,实现了无线齿轮故障监测。通过LabVIEW软件和相关硬件,可以实现对齿轮箱振动信号的采集、传输和故障识别,集远程采集、数据库存储…...
IM 即时通讯系统-01-概览
前言 有时候希望有一个 IM 工具,比如日常聊天,或者接受报警信息。 其实主要是工作使用,如果是接收报警等场景,其实DD这种比较符合场景。 那么有没有必要再创造一个DD呢? 答案是如果处于个人的私有化使用࿰…...
【人工智能】 在本地运行 DeepSeek 模型:Ollama 安装指南
持续更新。。。。。。。。。。。。。。。 【人工智能】 在本地运行 DeepSeek 模型:Ollama 安装指南 安装 Ollama安装 DeepSeek 模型选择版本 ,版本越高,参数越多 性能越好使用 DeepSeek 模型 安装 Ollama 访问 Ollama 官网: 前往 https://oll…...
【Linux系统】信号:信号保存 / 信号处理、内核态 / 用户态、操作系统运行原理(中断)
理解Linux系统内进程信号的整个流程可分为: 信号产生 信号保存 信号处理 上篇文章重点讲解了 信号的产生,本文会讲解信号的保存和信号处理相关的概念和操作: 两种信号默认处理 1、信号处理之忽略 ::signal(2, SIG_IGN); // ignore: 忽略#…...
探索 Copilot:开启智能助手新时代
探索 Copilot:开启智能助手新时代 在当今数字化飞速发展的时代,人工智能(AI)正以前所未有的速度改变着我们的工作和生活方式。而 Copilot 作为一款强大的 AI 助手,凭借其多样的功能和高效的应用,正在成为众…...
解锁豆瓣高清海报(二) 使用 OpenCV 拼接和压缩
解锁豆瓣高清海报(二): 使用 OpenCV 拼接和压缩 脚本地址: 项目地址: Gazer PixelWeaver.py pixel_squeezer_cv2.py 前瞻 继上一篇“解锁豆瓣高清海报(一) 深度爬虫与requests进阶之路”成功爬取豆瓣电影海报之后,本文将介绍如何使用 OpenCV 对这些海报进行智…...
LFM2.5-1.2B-Thinking-GGUF开源生态初探:与Ollama等工具的对比与集成
LFM2.5-1.2B-Thinking-GGUF开源生态初探:与Ollama等工具的对比与集成 1. 开源大模型本地部署生态概览 近年来,开源大模型本地部署工具呈现百花齐放的局面。从早期的单一模型加载器,发展到如今功能丰富的模型管理生态系统,开发者…...
保姆级教程:手把手教你用PHPStudy本地搭建GaussDB开发环境(附JDBC连接避坑指南)
从零搭建GaussDB开发环境:PHPStudy集成与JDBC连接实战 在数据库技术快速迭代的今天,国产数据库正逐渐成为企业级应用的新选择。GaussDB作为一款高性能分布式数据库,其学习门槛却让不少开发者望而却步。本文将带你绕过那些官方文档中语焉不详的…...
CLIP ViT-H-14多场景适配方案:教育题库图像索引、医疗报告配图推荐、设计素材库检索
CLIP ViT-H-14多场景适配方案:教育题库图像索引、医疗报告配图推荐、设计素材库检索 1. 项目概述 CLIP ViT-H-14图像编码服务是基于CLIP ViT-H-14(laion2B-s32B-b79K)模型的图像特征提取解决方案。这项服务通过RESTful API和Web界面两种方式,为不同行业…...
Beyond Compare 5 永久激活完全指南:从入门到精通
Beyond Compare 5 永久激活完全指南:从入门到精通 【免费下载链接】BCompare_Keygen Keygen for BCompare 5 项目地址: https://gitcode.com/gh_mirrors/bc/BCompare_Keygen 一、问题诊断:Beyond Compare 5授权痛点解析 1.1 评估期结束的功能限制…...
Windows更新修复新范式:Reset-Windows-Update-Tool的系统化解决方案
Windows更新修复新范式:Reset-Windows-Update-Tool的系统化解决方案 【免费下载链接】Reset-Windows-Update-Tool Troubleshooting Tool with Windows Updates (Developed in Dev-C). 项目地址: https://gitcode.com/gh_mirrors/re/Reset-Windows-Update-Tool …...
小白也能玩转GLM-4V-9B:免费开源多模态模型部署全流程
小白也能玩转GLM-4V-9B:免费开源多模态模型部署全流程 1. 环境准备与快速部署 1.1 硬件要求与系统配置 GLM-4V-9B作为90亿参数的多模态模型,对硬件有一定要求: GPU推荐:至少24GB显存的显卡(如RTX 4090)…...
[模电]从PN结到实用电路:二极管的深度解析与设计指南
1. PN结:二极管的物理基础 想象一下把一块P型半导体和N型半导体紧密贴合在一起,就像把两块不同颜色的橡皮泥揉捏在一起。P型半导体里充满了带正电的"空穴"(可以理解为缺少电子的位置),而N型半导体则富含自由…...
手把手教你用Arm Cortex-A715手册:从RAS到调试,一份给芯片设计者的实战笔记
Cortex-A715实战指南:芯片设计者的RAS与调试技术精要 在当今高性能计算领域,Arm Cortex-A715处理器核心凭借其卓越的能效比和性能表现,已成为众多芯片设计项目的首选。本文将从工程实践角度,深入剖析Cortex-A715的两个关键子系统&…...
Phi-4-mini-reasoning企业落地案例:集成至内部知识库的逻辑问答模块
Phi-4-mini-reasoning企业落地案例:集成至内部知识库的逻辑问答模块 1. 项目背景与需求 企业内部知识库系统通常面临一个共同挑战:员工在查找专业问题时,往往需要花费大量时间筛选信息,特别是涉及数学计算、逻辑推理等需要多步分…...
别再死记硬背DAQmx流程了!LabVIEW数据采集核心逻辑拆解:以USB-6008正弦波实验为例
从设计模式视角重构LabVIEW数据采集:以USB-6008正弦波实验为例 当LabVIEW新手第一次接触DAQmx数据采集时,往往会被"创建任务→添加通道→配置时钟→开始任务→读取数据→清除任务"的固定流程所困扰。这种机械记忆不仅容易遗忘,更难…...
