STL -萃取特性迭代器
1. STL简单概述
a. STL六大组成部分
- 容器(Container)
- 空间配置器(allocator)
- 算法(Algorithm)
- 迭代器(Iterator)
- 仿函数(Function object)
- 适配器(Adaptor)
b. STL六大组件内在联系
-
空间分配器为容器分配内存空间。
注意:无论是为什么类型分配内存,分配器都 只是分配内存,而不执行构造函数
-
算法 只关心具体的做法,而不关心是什么 容器 。所以需要 迭代器 作为 容器 与 算法 的桥梁,将两者连接起来。
-
算法 中会常常搭配 仿函数 来更好的完成其工作
-
适配器 将一个class 的接口转换为另一个 class 的接口,使原本因接口不兼容而不能合作的 class,可以一起运作。
-
容器 所使用的 迭代器,其相当一部分操作是在 容器 内实现的。
2. 组件部分详细信息
a. 内存配置器
-
容器使用配置器来进行内存空间的分配、释放,其相关头文件为
stl_alloc.h
等。空间分配器有如下两种,这两种分配方式各有各的好坏。
- 第一级分配器
__malloc_alloc_template
,即时分配即时释放, - 第二级分配器
__default_alloc_template
,小型内存池。
- 第一级分配器
-
容器中通过调用配置器的静态函数来 分配、释放 内存,而配置器则在底层调用
malloc
和free
来满足用户需求。
b. 迭代器
-
迭代器的本质就是"指针",只不过这个指针有点特别,它比较智能。
-
算法通过迭代器来对容器进行操作,使算法不必了解容器本身的结构。
-
迭代器探幽
-
迭代器的相关实现 (源码位于
stl_iterator.h
和stl_iterator_base.h
)COPYtemplate <class _Category, class _Tp, class _Distance = ptrdiff_t,class _Pointer = _Tp *, class _Reference = _Tp &>struct iterator {typedef _Category iterator_category; // 迭代器的种类typedef _Tp value_type; // 迭代器所指对象的类型typedef _Distance difference_type; // 两两迭代器之间,距离的类型typedef _Pointer pointer; // 迭代器所指对象的指针typedef _Reference reference; // 迭代器所指对象的引用 };
-
迭代器又细分为以下几种类型
COPY// 迭代器的tag。对应类型的迭代器中,其iterator_category就是对应的tag struct input_iterator_tag {}; struct output_iterator_tag {}; struct forward_iterator_tag : public input_iterator_tag {}; struct bidirectional_iterator_tag : public forward_iterator_tag {}; struct random_access_iterator_tag : public bidirectional_iterator_tag {};// 输入迭代器 template <class _Tp, class _Distance> struct input_iterator {typedef input_iterator_tag iterator_category;typedef _Tp value_type;typedef _Distance difference_type;typedef _Tp* pointer;typedef _Tp& reference; }; // 输出迭代器 struct output_iterator {typedef output_iterator_tag iterator_category;typedef void value_type;typedef void difference_type;typedef void pointer;typedef void reference; }; // 正向迭代器 template <class _Tp, class _Distance> struct forward_iterator {typedef forward_iterator_tag iterator_category;typedef _Tp value_type;typedef _Distance difference_type;typedef _Tp* pointer;typedef _Tp& reference; };// 双向迭代器 template <class _Tp, class _Distance> struct bidirectional_iterator {typedef bidirectional_iterator_tag iterator_category;typedef _Tp value_type;typedef _Distance difference_type;typedef _Tp* pointer;typedef _Tp& reference; }; // 随机访问迭代器 template <class _Tp, class _Distance> struct random_access_iterator {typedef random_access_iterator_tag iterator_category;typedef _Tp value_type;typedef _Distance difference_type;typedef _Tp* pointer;typedef _Tp& reference; };
-
迭代器中的
iterator_category
和value_type
等等,它们只是类型名。那么迭代器是如何将这些信息返回给调用者呢?
实际上,SGI STL灵活的使用了模板参数推导的特性来完成这些任务,例如如下代码COPY// iterator_category template <class _Tp, class _Distance> inline input_iterator_tag iterator_category(const input_iterator<_Tp, _Distance>&) {return input_iterator_tag(); }inline output_iterator_tag iterator_category(const output_iterator&) {return output_iterator_tag(); } #define __ITERATOR_CATEGORY(__i) iterator_category(__i) // value_type template <class _Tp, class _Distance> inline _Tp* value_type(const bidirectional_iterator<_Tp, _Distance>&) {return (_Tp*)(0); }template <class _Tp, class _Distance> inline _Tp* value_type(const random_access_iterator<_Tp, _Distance>&) {return (_Tp*)(0); } #define __VALUE_TYPE(__i) value_type(__i)
当不同类型的指针使用宏定义
__VALUE_TYPE
时,由于模板参数推导的特点,程序会调用参数类型相匹配的函数。既然参数类型匹配,那么返回的也一定是匹配的类型。 -
Traits
技术(重中之重)-
iterator_traits
-
iterator_traits 技术用于萃取出iterator的对应类型,例如
value_type
、iterator_category
等等。
iterator本身便可以使用对应宏定义(例如__VALUE_TYPE
)来取出对应类型。但原生指针并没有这些方法,所以需要套一层iterator_traits
,让iterator_traits
“帮助”原生指针,将所需的相关信息返回给调用者。 -
iterator_traits
相关源码COPYtemplate <class _Iterator> struct iterator_traits { typedef typename _Iterator::iterator_category iterator_category; typedef typename _Iterator::value_type value_type; typedef typename _Iterator::difference_type difference_type; typedef typename _Iterator::pointer pointer; typedef typename _Iterator::reference reference; };template <class _Tp> struct iterator_traits<_Tp*> { typedef random_access_iterator_tag iterator_category; typedef _Tp value_type; typedef ptrdiff_t difference_type; typedef _Tp* pointer; typedef _Tp& reference; };
可以看到,
iterator_traits
对待iterator和原生指针的方式,是不一样的。
-
-
type_traits
-
iterator_traits
技术只能用来规范迭代器,对于迭代器之外的东西没有加以规范。所以type_traits
就应运而生。 -
iterator_traits
是萃取迭代器的特性,而__type_traits
是萃取型别的特性。
__type_traits
有如下几个类型has_trivial_default_constructor
—— 是否使用默认构造函数has_trivial_copy_constructor
—— 是否使用默认拷贝构造函数has_trivial_assignment_operator
—— 是否使用默认赋值运算符has_trivial_destructor
—— 是否使用默认析构函数is_POD_type
—— 是否是POD
类型
返回的是__true_type
或__false_type
结构
-
其相关源码如下
COPYstruct __true_type {}; struct __false_type {};template <class _Tp> struct __type_traits {typedef __true_type this_dummy_member_must_be_first;/* Do not remove this member. It informs a compiler whichautomatically specializes __type_traits that this__type_traits template is special. It just makes sure thatthings work if an implementation is using a templatecalled __type_traits for something unrelated. *//* The following restrictions should be observed for the sake ofcompilers which automatically produce type specific specializationsof this class:- You may reorder the members below if you wish- You may remove any of the members below if you wish- You must not rename members without making the correspondingname change in the compiler- Members you add will be treated like regular members unlessyou add the appropriate support in the compiler. */typedef __false_type has_trivial_default_constructor;typedef __false_type has_trivial_copy_constructor;typedef __false_type has_trivial_assignment_operator;typedef __false_type has_trivial_destructor;typedef __false_type is_POD_type; };__STL_TEMPLATE_NULL struct __type_traits<int> {typedef __true_type has_trivial_default_constructor;typedef __true_type has_trivial_copy_constructor;typedef __true_type has_trivial_assignment_operator;typedef __true_type has_trivial_destructor;typedef __true_type is_POD_type; };
-
-
-
应用
-
为什么迭代器要分这么多的类型呢?原因是为了实现STL速度与效率的提高。
根据迭代器的类型,算法可以对该种类的迭代器使用效率最高的操作方式。
例如,如果对char*类型的iterator执行copy操作,那么copy函数就可以直接使用memcpy来完成操作,而不是遍历复制再构造。如此以提高算法的效率。
请看如下源码:COPYvector<_Tp, _Alloc>::_M_insert_aux(iterator __position, const _Tp& __x) {/* .... */__STL_TRY{// 当vector的成员函数调用 uninitialized_copy 时,程序会根据迭代器类型执行特定的 uninitialized_copy操作__new_finish = uninitialized_copy(_M_start, __position, __new_start);construct(__new_finish, __x);++__new_finish;__new_finish = uninitialized_copy(__position, _M_finish, __new_finish);} __STL_UNWIND((destroy(__new_start, __new_finish),_M_deallocate(__new_start, __len)));/* .... */ }// 如果是char*类型的迭代器就直接调用memmove。如果不是,则调用使用迭代器的uninitialized_copy函数 template <class _InputIter, class _ForwardIter> inline _ForwardIter uninitialized_copy(_InputIter __first, _InputIter __last,_ForwardIter __result) {return __uninitialized_copy(__first, __last, __result,// 注意到这里获取了迭代器所指向对象的类型__VALUE_TYPE(__result)); }// 如果迭代器是一个指向某个对象的指针,则调用内含_Tp*类型参数的__uninitialized_copy template <class _InputIter, class _ForwardIter, class _Tp> inline _ForwardIter __uninitialized_copy(_InputIter __first, _InputIter __last,_ForwardIter __result, _Tp*) {// 注意这里获取了迭代器所指对象的is_POD信息typedef typename __type_traits<_Tp>::is_POD_type _Is_POD;return __uninitialized_copy_aux(__first, __last, __result, _Is_POD()); }// 如果这个对象类型是POD的,直接copy以提高效率 template <class _InputIter, class _ForwardIter>` inline _ForwardIter __uninitialized_copy_aux(_InputIter __first, _InputIter __last,_ForwardIter __result,__true_type) {return copy(__first, __last, __result); } // 否则,只能一个个的遍历并执行构造函数 template <class _InputIter, class _ForwardIter> _ForwardIter __uninitialized_copy_aux(_InputIter __first, _InputIter __last,_ForwardIter __result,__false_type) {_ForwardIter __cur = __result;__STL_TRY {for ( ; __first != __last; ++__first, ++__cur)_Construct(&*__cur, *__first);return __cur;}__STL_UNWIND(_Destroy(__result, __cur)); }
-
-
c. 容器
- vector
- vector的本质就是一个空间连续数组。与普通数组不同的是,该数组"可长可短"。
- vector的核心成员是三个迭代器,分别为
_Tp* _M_start
—— 指向所分配数组的起始位置_Tp* _M_finish
—— 指向已使用空间的末端位置+1_Tp* _M_end_of_storage
—— 指向所分配数组的末尾位置+1
- list
- list是一个头尾相连的双向环状链表,由一个个节点头尾相连所构成。
- 其关键的成员只有一个,
_List_node<_Tp>* _M_node
—— 指向链表的末尾节点,该节点的成员_M_next
指向的是链表的起始节点。
相关文章:
STL -萃取特性迭代器
1. STL简单概述 a. STL六大组成部分 容器(Container)空间配置器(allocator)算法(Algorithm)迭代器(Iterator)仿函数(Function object)适配器(Ad…...
python pandas写入csv
在Python的Pandas库中,可以使用to_csv方法将DataFrame对象写入CSV文件。以下是一个简单的示例: import pandas as pd# 创建一个DataFrame对象 data {Name: [Alice, Bob, Charlie, David],Age: [25, 30, 35, 40],City: [New York, Los Angeles, Chicago…...
oracle 数据库建集群式数据库的DBLINK的语法
根据需要修改以下红色字体的部分即可。 1、连接集群式数据库DBLINK语法 create public database link 自定义的dblink名字 connect to 连接对方数据库的用户名 identified by "密码" using (DESCRIPTION (ADDRESS_LIST (FAILOVER ON) (LOAD_BALANCE OFF) …...

基于JAVA的毕业设计分配选题系统 开源项目
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 专业档案模块2.2 学生选题模块2.3 教师放题模块2.4 选题审核模块 三、系统展示四、核心代码4.1 查询专业4.2 新增专业4.3 选择课题4.4 取消选择课题4.5 审核课题 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpri…...
Android 接入指纹识别
接入指纹框架:https://github.com/Tencent/soter implementation com.github.Tencent.soter:soter-wrapper:2.0.91.Application中初始化 class IApplication : Application() {override fun onCreate() {super.onCreate()instance thisinitSort()}private fun in…...

如何通过代理IP安全使用Linkedln领英?
LinkedIn是跨境外贸必备的拓客工具,世界各地的许多专业人士都使用领英来作为发布和共享内容的主要工具,这使得它成为跨境出海必备的渠道工具。 但是不少做外贸的朋友都知道,领英账号很容易遭遇限制封禁,但如果善用工具࿰…...
嵌入式驱动学习第一周——定时器与延时函数
前言 这篇博客一起学习定时器,定时器是最常用到的功能之一,其最大的作用之一就是提供了延时函数。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程,未来预计四个月将高强度更新本专栏,喜欢的可以关注本博主并订阅本专栏&…...
Tips杂记
🥲 🥸 🤌 🫀 🫁 🥷 🐻❄️🦤 🪶 🦭 🪲 🪳 🪰 🪱 🪴 🫐 🫒 🫑…...
可以用numpy为for加速
Numpy除了用于科学计算,还有一个功能是可以代替某些for循环,进行同样的功能实现,有于是向量矩阵运算,碰到复杂的for时,计算速度可以提高,从而提高程序性能。以下是一些常用的NumPy函数和操作,可…...
cartographer ceres后端优化
这里引用一篇文章 https://zhuanlan.zhihu.com/p/567635409 因为cartographer中的代码有的地方添加了AddParameterBlock,有的地方没有添加,会引起歧义,原来AddParameterBlock可以隐式添加优化变量,这篇文章介绍了具体原因,核心内容如下: AddParameterBlock的作用作用一:…...

day57 集合 List Set Map
List实现类 List接口特点:元素有序 可重复 Arraylist 可变数组 jdk 8 以前Arraylist容量初始值10 jdk8 之后初始值为0,添加数据时,容量为10; ArrayList与Vector的区别? LinkList:双向链表 优点࿱…...

蓝桥杯:真题讲解3(C++版)附带解析
报纸页数 来自:2016年七届省赛大学C组真题(共8道题) 分析: --画出报纸长的样子,如果我们在上面多画一张报纸,那么就符合题意的5,6,11,12。 观察这张图:观察3…...

继续预训练对大语言模型的影响
翻译自文章:Investigating Continual Pretraining in Large Language Models: Insights and Implications 摘要 本文研究了大型语言模型(LLMs)中不断学习(CL)的不断发展领域,重点是制定有效和可持续的训练…...
关于空频变换的知识点
1.DCT变换: 离散余弦变换是一种将图像从空域转换到频域的技术,它可以将图像分解为频域分量。对于RGB图像,它由红色(R)、绿色(G)和蓝色(B)三个通道组成。当应用DCT变换时…...

纯css实现-让字符串在文字少时显示为居中对齐,而在文字多时显示为左对齐
纯css实现-让字符串在文字少时显示为居中对齐,而在文字多时显示为左对齐 使用flex实现 思路 容器样式(.container): Flex容器的BFC性质使得其内部的子元素(.text-box)在水平方向上能够居中,通过justify-c…...

初学HTMLCSS——盒子模型
盒子模型 盒子:页面中所有的元素(标签),都可以看做是一个 盒子,由盒子将页面中的元素包含在一个矩形区域内,通过盒子的视角更方便的进行页面布局盒子模型组成:内容区域(content&…...

吸猫毛空气净化器哪个好?推荐除猫毛好的宠物空气净化器品牌
如今,越来越多的家庭选择养宠物!虽然家里变得更加温馨,但养宠可能会带来异味和空气中的毛发增多可能会引发健康问题,这也是一个大问题。 但我不想家里到处都是异味,尤其是便便的味道,所以很需要一款能够处…...

【玩转408数据结构】线性表——双链表、循环链表和静态链表(线性表的链式表示 下)
知识回顾 在前面的学习中,我们已经了解到了链表(线性表的链式存储)的一些基本特点,并且深入的研究探讨了单链表的一些特性,我们知道,单链表在实现插入删除上,是要比顺序表方便的,但是…...

分布式概念
分布式概念 一、分布式介绍1.1 分布式计算1.1.1 分布式计算的方法1.1.1 分布式计算与互联网的普及1.1.2 分布式计算项目1.1.3 参与计算 1.2 分布式存储系统1.2.1 P2P 数据存储系统1.2.2 云存储系统 1.3 应用 二、分布式基础概念2.1 微服务2.2 集群2.3 分布式2.4 节点2.5 远程调…...
vue中的ref/reactive区别及原理
Vue中的ref和reactive是两种不同的数据响应式管理方式。 ref是Vue 3中新加入的特性,它可以将一个普通的JavaScript对象转换为响应式对象。通过ref创建的响应式对象在访问和修改时会自动触发重新渲染。ref返回的是一个包含value属性的对象,访问或修改数据…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...