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

STL -萃取特性迭代器

1. STL简单概述

a. STL六大组成部分

  1. 容器(Container)
  2. 空间配置器(allocator)
  3. 算法(Algorithm)
  4. 迭代器(Iterator)
  5. 仿函数(Function object)
  6. 适配器(Adaptor)

b. STL六大组件内在联系

  • 空间分配器为容器分配内存空间。

    注意:无论是为什么类型分配内存,分配器都 只是分配内存,而不执行构造函数

  • 算法 只关心具体的做法,而不关心是什么 容器 。所以需要 迭代器 作为 容器算法 的桥梁,将两者连接起来。

  • 算法 中会常常搭配 仿函数 来更好的完成其工作

  • 适配器 将一个class 的接口转换为另一个 class 的接口,使原本因接口不兼容而不能合作的 class,可以一起运作。

  • 容器 所使用的 迭代器,其相当一部分操作是在 容器 内实现的。

2. 组件部分详细信息

a. 内存配置器

  • 容器使用配置器来进行内存空间的分配、释放,其相关头文件为stl_alloc.h等。

    空间分配器有如下两种,这两种分配方式各有各的好坏。

    1. 第一级分配器__malloc_alloc_template,即时分配即时释放,
    2. 第二级分配器__default_alloc_template,小型内存池。
  • 容器中通过调用配置器的静态函数来 分配释放 内存,而配置器则在底层调用mallocfree来满足用户需求。

b. 迭代器

  • 迭代器的本质就是"指针",只不过这个指针有点特别,它比较智能。

  • 算法通过迭代器来对容器进行操作,使算法不必了解容器本身的结构。

  • 迭代器探幽

    • 迭代器的相关实现 (源码位于stl_iterator.hstl_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_categoryvalue_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技术(重中之重)

      1. iterator_traits
        
        • iterator_traits 技术用于萃取出iterator的对应类型,例如value_typeiterator_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和原生指针的方式,是不一样的。

      2. type_traits
        
        • iterator_traits技术只能用来规范迭代器,对于迭代器之外的东西没有加以规范。所以type_traits就应运而生。

        • iterator_traits是萃取迭代器的特性,而__type_traits是萃取型别的特性。
          __type_traits有如下几个类型

          1. has_trivial_default_constructor —— 是否使用默认构造函数
          2. has_trivial_copy_constructor —— 是否使用默认拷贝构造函数
          3. has_trivial_assignment_operator —— 是否使用默认赋值运算符
          4. has_trivial_destructor —— 是否使用默认析构函数
          5. 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. 容器

  1. vector
    • vector的本质就是一个空间连续数组。与普通数组不同的是,该数组"可长可短"。
    • vector的核心成员是三个迭代器,分别为
      1. _Tp* _M_start —— 指向所分配数组的起始位置
      2. _Tp* _M_finish —— 指向已使用空间的末端位置+1
      3. _Tp* _M_end_of_storage —— 指向所分配数组的末尾位置+1
  2. list
    • list是一个头尾相连的双向环状链表,由一个个节点头尾相连所构成。
    • 其关键的成员只有一个,_List_node<_Tp>* _M_node —— 指向链表的末尾节点,该节点的成员_M_next指向的是链表的起始节点。

相关文章:

STL -萃取特性迭代器

1. STL简单概述 a. STL六大组成部分 容器&#xff08;Container&#xff09;空间配置器&#xff08;allocator&#xff09;算法&#xff08;Algorithm&#xff09;迭代器&#xff08;Iterator&#xff09;仿函数&#xff08;Function object&#xff09;适配器&#xff08;Ad…...

python pandas写入csv

在Python的Pandas库中&#xff0c;可以使用to_csv方法将DataFrame对象写入CSV文件。以下是一个简单的示例&#xff1a; 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 接入指纹识别

接入指纹框架&#xff1a;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是跨境外贸必备的拓客工具&#xff0c;世界各地的许多专业人士都使用领英来作为发布和共享内容的主要工具&#xff0c;这使得它成为跨境出海必备的渠道工具。 但是不少做外贸的朋友都知道&#xff0c;领英账号很容易遭遇限制封禁&#xff0c;但如果善用工具&#xff0…...

嵌入式驱动学习第一周——定时器与延时函数

前言 这篇博客一起学习定时器&#xff0c;定时器是最常用到的功能之一&#xff0c;其最大的作用之一就是提供了延时函数。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程&#xff0c;未来预计四个月将高强度更新本专栏&#xff0c;喜欢的可以关注本博主并订阅本专栏&…...

Tips杂记

&#x1f972; &#x1f978; &#x1f90c; &#x1fac0; &#x1fac1; &#x1f977; &#x1f43b;‍❄️&#x1f9a4; &#x1fab6; &#x1f9ad; &#x1fab2; &#x1fab3; &#x1fab0; &#x1fab1; &#x1fab4; &#x1fad0; &#x1fad2; &#x1fad1…...

可以用numpy为for加速

Numpy除了用于科学计算&#xff0c;还有一个功能是可以代替某些for循环&#xff0c;进行同样的功能实现&#xff0c;有于是向量矩阵运算&#xff0c;碰到复杂的for时&#xff0c;计算速度可以提高&#xff0c;从而提高程序性能。以下是一些常用的NumPy函数和操作&#xff0c;可…...

cartographer ceres后端优化

这里引用一篇文章 https://zhuanlan.zhihu.com/p/567635409 因为cartographer中的代码有的地方添加了AddParameterBlock,有的地方没有添加,会引起歧义,原来AddParameterBlock可以隐式添加优化变量,这篇文章介绍了具体原因,核心内容如下: AddParameterBlock的作用作用一:…...

day57 集合 List Set Map

List实现类 List接口特点&#xff1a;元素有序 可重复 Arraylist 可变数组 jdk 8 以前Arraylist容量初始值10 jdk8 之后初始值为0&#xff0c;添加数据时&#xff0c;容量为10&#xff1b; ArrayList与Vector的区别&#xff1f; LinkList&#xff1a;双向链表 优点&#xff1…...

蓝桥杯:真题讲解3(C++版)附带解析

报纸页数 来自&#xff1a;2016年七届省赛大学C组真题&#xff08;共8道题) 分析&#xff1a; --画出报纸长的样子&#xff0c;如果我们在上面多画一张报纸&#xff0c;那么就符合题意的5&#xff0c;6&#xff0c;11&#xff0c;12。 观察这张图&#xff1a;观察3&#xf…...

继续预训练对大语言模型的影响

翻译自文章&#xff1a;Investigating Continual Pretraining in Large Language Models: Insights and Implications 摘要 本文研究了大型语言模型&#xff08;LLMs&#xff09;中不断学习&#xff08;CL&#xff09;的不断发展领域&#xff0c;重点是制定有效和可持续的训练…...

关于空频变换的知识点

1.DCT变换&#xff1a; 离散余弦变换是一种将图像从空域转换到频域的技术&#xff0c;它可以将图像分解为频域分量。对于RGB图像&#xff0c;它由红色&#xff08;R&#xff09;、绿色&#xff08;G&#xff09;和蓝色&#xff08;B&#xff09;三个通道组成。当应用DCT变换时…...

纯css实现-让字符串在文字少时显示为居中对齐,而在文字多时显示为左对齐

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

初学HTMLCSS——盒子模型

盒子模型 盒子&#xff1a;页面中所有的元素&#xff08;标签&#xff09;&#xff0c;都可以看做是一个 盒子&#xff0c;由盒子将页面中的元素包含在一个矩形区域内&#xff0c;通过盒子的视角更方便的进行页面布局盒子模型组成&#xff1a;内容区域&#xff08;content&…...

吸猫毛空气净化器哪个好?推荐除猫毛好的宠物空气净化器品牌

如今&#xff0c;越来越多的家庭选择养宠物&#xff01;虽然家里变得更加温馨&#xff0c;但养宠可能会带来异味和空气中的毛发增多可能会引发健康问题&#xff0c;这也是一个大问题。 但我不想家里到处都是异味&#xff0c;尤其是便便的味道&#xff0c;所以很需要一款能够处…...

【玩转408数据结构】线性表——双链表、循环链表和静态链表(线性表的链式表示 下)

知识回顾 在前面的学习中&#xff0c;我们已经了解到了链表&#xff08;线性表的链式存储&#xff09;的一些基本特点&#xff0c;并且深入的研究探讨了单链表的一些特性&#xff0c;我们知道&#xff0c;单链表在实现插入删除上&#xff0c;是要比顺序表方便的&#xff0c;但是…...

分布式概念

分布式概念 一、分布式介绍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中新加入的特性&#xff0c;它可以将一个普通的JavaScript对象转换为响应式对象。通过ref创建的响应式对象在访问和修改时会自动触发重新渲染。ref返回的是一个包含value属性的对象&#xff0c;访问或修改数据…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...