STL源码剖析 笔记之三 迭代器

2023-05-16

第三章 迭代器概念与traits编程技法
《Design Patterns》 中提供有23个设计模式的完整描述。
迭代器模式定义如下,提供一种方法,使之能够依序巡防某个聚合物(容器)所含的各个元素,而又无需暴露该聚合物的内部表述方式。
迭代器是一种Smart Pointer,迭代器是一种行为类似指针的对象,而指针的各种行为中最重要也是最常见的就是dereference和member access。
因此,迭代器最重要的工作就是对operator*和operator->进行重载。
auto_ptr的源码在<memory>中。 explicit修饰构造,只能显示调用。
我们需要为每个容器设计一个行为类似指针的外衣,也就是迭代器。满足以下功能:当我们dereference这一迭代器时,传回结点对象;当我们递增该迭代器时,应该指向下一个结点对象。为了满足任何形态的结点,该迭代器应该被设计成一个class template。
为了实现一个针对某容器的迭代器,我们暴露了太多的实现细节:
1.为了制作begin和end迭代器,暴露了结点;2.在迭代器中为了达成operator++,暴露了next()函数。
因此,把迭代器的设计工作交给容器设计者,这样就可以封装所有的实现细节。
迭代器相应类型
得到迭代器所指对象的类型,也就是该迭代器的value_type。
1.参数推导(个人理解,通过构建对应value_type类型的传入参数,在模板中使用value_type)
    缺点,value_type用作返回值的时候,此方法无法做到。
2.声明内嵌类型,设计偏特化版本以适应原生指针的情况。
    template <class I>
    struct iterator_traits{  //特性萃取机
        typedef typename I::value_type value_type;
    }
  可以有原生指针的偏特化版,和const指针的偏特化版。
traits可以萃取各个迭代器的特性,也就是迭代器的相应类型。
当然这个特性萃取机要想有效运作,每个迭代器必须遵守约定,自行以定义内嵌类型定义的方式定义出相应的类型。
常用的迭代器相应类型:value type,difference type,pointer,reference,iterator catagory。
iterator_traits必须为传入类型为指针和常量指针的情况,设计特化版本。
template <class T, class Alloc = alloc>
class list {
public:      
  typedef T value_type;
  typedef value_type* pointer;
  typedef const value_type* const_pointer;
  typedef value_type& reference;
  typedef const value_type& const_reference;
  typedef list_node* link_type;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
  //...
1. value type
所谓 value type,是指迭代器所指对象的类型。任何一个打算与STL算法有完美搭配的class,都应该定义自己的 value type内嵌类型。
2. difference type
difference type用来表示两个迭代器之间的距离,因此它也可以用来表示一个空间容器的最大容量。因为对于连续空间的容器而言,头尾之间的距离就是其最大容量。
如STL的count()(在文件<stl_algo.h>中),为什么计数器必须要用这个 difference type来表示?
针对相应类型 difference type,traits有两个针对原生指针而写的偏特化版。
如果是原生指针,则直接typedef ptrdiff_t difference_type;否则需要typedef typename I::  difference_type  difference_type。
3. reference type     NodeItem&    引用类型与左值?
从“迭代器所指之物的内容是否允许改变”的角度,迭代器分为两种:
不允许改变所指对象内容者,constant iterators; 允许改变所指对象内容者,mutable iterators
当我们对一个mutable  iterators进行dereference操作时,返回的应该是个左值,因此应该以by reference的方式进行。
当p是个mutable iterators,如果value type是T,*p应该是T&。
当p是个constant iterators,如果value type是T,*p应该是const T&。
针对相应类型 difference type,traits同样有两个针对原生指针而写的偏特化版。
4.pointer type     NodeItem*
我们可以传回一个pointer,指向迭代器所指之物。
针对相应类型 difference type,traits同样有两个针对原生指针而写的偏特化版。
5. iterator_catagory
根据移动特性和施行操作,迭代器被分为五类:
1.Input Iterator                 read only
2.Output Iterator                write only
3.Forward Iterator               允许写入型算法在此种迭代器所形成的区间上进行读写操作。 
4.Bidirectional Iterator        可双向移动。某些算法需要逆向走访迭代器区间。
以上四种迭代器都只公寓一部分指针算术能力,前三种支持operator++,第四种再加上operator--。
5.Random Access Iterator    涵盖所有指针算术能力,包括p+n,p-n,p[n],p1-p2,p1<p2。
概念与强化,是架构STL的重要观念(Austern98)。
以上五种迭代器的分类和从属关系;
     Input Iterator     Output Iterator 
         Forward Iterator
         Bidirectional Iterator
         Random Access Iterator
我们应该针对每一种寄存器,实现特定的算法,来达到最大的效率。
1.判断迭代器的类型,然后调用不同的算法实现函数。
  但是这样在执行期间才确定使用哪个版本的算法函数,影响效率。
2.使用函数重载机制。
  为五种类型的迭代器声明有从属关系的标记类型:
 struct input_iterator_tag{};
 struct output_iterator_tag{};
 struct forward_iterator_tag::public input_iterator_tag{};
 struct biddirectional_iterator_tag::public   forward_iterator_tag  {};
 struct random_access_iterator_tag:: public  biddirectional_iterator_tag::  {};
然后为各个版本的算法实现函数,添加额外一个参数,来激活重载机制。
在各个版本的 算法实现函数之上,应该开放一个对外的控制接口,在此接口函数中,需要根据traits推导出迭代器类型。
iterator_traits<InputIterator>::iterator_category();
为此tratis中必须定义相应的类型:typedef typename I::iterator_category  iterator_category;
同样的, 针对相应类型 difference type,traits需要有两个针对原生指针而写的偏特化版。
注:1.任何一个迭代器,其类型永远应该落在“该迭代器所隶属的各种类型中,最强化的那个”。
   2.STL命名规则,以算法所能接收的最低阶迭代器类型,来为其迭代器类型参数 命名。
消除单纯传递调用的函数,当参数未能完全吻合时,类的继承机制会自动传递调用,到其(迭代器类型)父类的相应匹配。
为了符合规范,任何迭代器都应该提供五个内嵌相应类型,以便traits萃取。
STL提供了一个iterator类,如果每个迭代器都继承自它,就可以符合STL所需规范。
template <class Category, class T, class Distance = ptrdiff_t,
          class Pointer = T*, class Reference = T&>
struct iterator {
  typedef Category  iterator_category;
  typedef T         value_type;
  typedef Distance  difference_type;
  typedef Pointer   pointer;
  typedef Reference reference;
};//<stl_iterator.h>
traits编程技法 利用内嵌类型的编程技巧与编译器的template参数推导功能,
增强C++未能提供的关于类型认证方面的能力,弥补C++不为强类型语言的遗憾。
__type_traits
//以下代码在<type_traits.h>
struct __true_type {};
struct __false_type {};
template <class type>
struct __type_traits { 
   typedef __true_type     this_dummy_member_must_be_first; 
   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;
};
然后 <type_traits.h>还为所有C++的标量类型提供了 __type_traits的特化版本。
用法:首先用value_type()萃取出迭代器的value type,然后再利用 __type_traits判断该类型是否具备某种属性比如 is_POD_type。
从而可以对应不同的重载函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STL源码剖析 笔记之三 迭代器 的相关文章

  • AVL分析飞机气动特性

    AVL xff0c 全称为Athena Vortex Lattice xff0c 是MIT的Mark Drela教授开发的一个气动分析程序 程序最初由Harold Youngren 1988年为MIT Athena TODOR航空软件集编写
  • ros_arduino_bridge+arduino+l298n控制编码电机(Arduino uno)

    踩了许多坑 xff0c 看了许多教程 xff0c 终于成功用ros arduino桥的方法实现了对电机的控制 xff0c 希望大家能通过我的教训少走一些弯路 注 xff1a 本教程的所有代码可以进入我主页下载 step1 ubuntu下安装
  • 典型TI LaunchPad 比较

    型号主芯片主频资源尺寸支持软件参考价格MSP EXP432P401R MSP432P401R 48MHz 256KB Flash 64KB RAM 32KB ROM 9 5cm 5 85cm Keil Energia CCS 199 EK
  • 关于反序列异常问题

    异常显示序列号不一致 xff0c 序列化和反序列化受serialVersionUID序列号控制 xff0c 异常原因 xff1a 对象序列化时忘了写显式序列号 xff0c 然后再反序列化才重写的序列号 xff0c 也就是 序列化和反序列化的
  • ros消息和服务error:The manifest (with format version 2) must not contain the following tags: run_depend

    在按ROS入门教程 xff08 点击打开链接 xff09 行进过程中到了执行 rosmsg show beginner tutorials Num 命令时 xff0c 出现提示 The manifest with format versio
  • 【Vue + ElementUI】el-progress 各类常用场景(自动计算percentage,format自定义显示文字)

    效果图 xff1a 1 当前数据结构 progressList planNum 150 计划数量 completeNum 80 完成数量 planNum 70 completeNum 70 planNum 70 completeNum 90
  • 音乐播放器的一些思路

  • Arduino笔记实验(初级阶段)—Keypad小键盘

    Arduino笔记实验 初级阶段 Keypad小键盘 文章目录 Arduino笔记实验 初级阶段 Keypad小键盘前言一 电路图二 集成库方案 Keypad 三方集成库代码实验效果展示 三 基于Arduino原生方案4 4按键膜结构图代码
  • Arduino笔记实验(初级阶段)—火焰传感器+有源蜂鸣器实验

    Arduino笔记实验 初级阶段 火焰传感器 43 有源蜂鸣器实验 文章目录 Arduino笔记实验 初级阶段 火焰传感器 43 有源蜂鸣器实验前言一 电路图二 火焰传感器 4引脚 有源蜂鸣器代码实验效果展示 三 火焰传感器火焰传感器模块示
  • Arduino笔记实验(初级阶段)—DHT11温湿度传感器

    Arduino笔记实验 初级阶段 DHT11温湿度传感器 文章目录 Arduino笔记实验 初级阶段 DHT11温湿度传感器前言一 电路图二 DHT11温湿度传感器实验代码实验效果展示 三 DHT11温湿度传感器实验总结 前言 自学笔记 x
  • C语言笔记-26-网络-UDP网络编程

    C语言笔记 26 网络 UDP网络编程 文章目录 C语言笔记 26 网络 UDP网络编程前言一 UDP编程模型概括三 UDP编程模型代码UDP服务端UDP客户端 总结 前言 自学笔记 xff0c 没有历史知识铺垫 xff08 省略百度部分
  • C++笔记-6-c++静态与单例

    C 43 43 笔记 6 c 43 43 静态与单例 文章目录 C 43 43 笔记 6 c 43 43 静态与单例前言一 静态静态成员变量静态成员函数 二 单例饿汉式懒汉式 总结 前言 自学笔记 xff0c 没有历史知识铺垫 xff08
  • C++笔记-4-c++类与继承

    C 43 43 笔记 4 c 43 43 类与继承 文章目录 C 43 43 笔记 4 c 43 43 类与继承前言一 类 Class 构造 析构函数拷贝构造和拷贝赋值 二 继承总结 前言 自学笔记 xff0c 没有历史知识铺垫 xff08
  • C++笔记-5-c++成员变量、函数指针

    C 43 43 笔记 5 c 43 43 成员变量 函数指针 文章目录 C 43 43 笔记 5 c 43 43 成员变量 函数指针前言一 成员变量指针二 成员函数指针总结 前言 自学笔记 xff0c 没有历史知识铺垫 xff08 省略百度
  • Qt实现的计算器

    写在前边 xff1a 这篇文章只是来带着大家一起实现一个基于Qt的计算器 中间会出现很多概念 xff0c 我们不做拓展介绍 xff0c 大家只要知道怎么用就好 xff0c 如果有需要我们后续再详细的对每个模块解析 1 首先介绍一下Qt xf
  • 【vue-element-admin笔记】

    vue element admin项目 xff08 1 xff09 一 使用步骤1 引入库2 出现问题 总结 一 使用步骤 1 引入库 代码如下 xff08 示例 xff09 xff1a git clone https span class
  • 无人机从零到一(组装、校准到起飞)

    一 组装 xff08 螺旋桨可以最后装 xff09 机械结构配置 xff1a 名称型号飞控Pixhawk 2 4 8 xff08 带安全开关 xff0c 蜂鸣器 xff0c 还买了减震板 xff09 螺旋桨8045 ABS xff08 33
  • C++11的多线程线程参数传递,指针与引用

    void foo std this thread sleep for std chrono seconds 1 int main std thread t std cout lt lt 34 before starting joinable
  • 学习(二):I2C、SPI、UART、CAN的特点与区别

    官网教程链接 xff1a https ardupilot org dev docs code overview sensor drivers html I2C 一个主机 xff0c 允许多个从机一种相对简单的通信协议 xff0c 适合短距离
  • C++ Qt 两字节相加(和)的校验位

    函数名称 xff1a checkSum 函数功能 xff1a 校验位 帧头 43 数据段按2字节累加和 若数据段个数为奇数 xff0c 则累加和时在数据段后方补1个字节0x00 函数参数 xff1a QByteArray 帧头 43 数据段

随机推荐

  • 考研复习C++基础问答题(六)

    1 C 43 43 中存储类有哪些 xff1f 存储类定义 C 43 43 程序中变量 函数的范围 xff08 可见性 xff09 和生命周期 这些说明符放置在它们所修饰的类型之前 下面列出 C 43 43 程序中可用的存储类 xff1a
  • STM32CubeMX编辑规范(02)

    STM32CubeMX编辑规范 目录 STM32CubeMX编辑规范前言一 代码编写范围二 项目结构三 单独外设配置四 代码生成设置五 高级设置 前言 采用STM32CubeMX的编辑规范可以更好的在不同的芯片上移植 xff0c 修改外设可
  • 机器人局部避障的动态窗口法DWA (dynamic window approach)-matlab代码修改及动态障碍物避障效果

    具体效果视频 xff1a DWA动态障碍物 哔哩哔哩 https b23 tv pQp6ne 一 源码及问题 最初的源码链接https blog csdn net heyijia0327 article details 44983551 改
  • QQ可以用十六进制登录哦

    又到装逼 时刻了 平常人登QQ是这样的 xff1a 如果我告诉你 xff1a 还可以这样登录 xff0c 你信吗 xff1f 显然我成功了 xff0c 你呢 xff1f 想知道如何快速把QQ号转换为十六进制吗 xff1f 评论里告诉你 xf
  • Keil C51详细安装教程(最新版)

    Keil C51 0x00 说在前面0x01 资源获取0x02 软件安装0x03 还有一步 xff08 重要 xff09 0x04 小问题 0x00 说在前面 x1f4e2 Keil 5常用的分两个版本 xff0c C51和MDK C51用
  • Java学习之JavaWeb篇

    图床路径 Kuang JavaWeb Java Web 1 基本概念 web开发 web xff0c 网页的意思 xff0c www baidu com静态web html xff0c css提供给所有人看的数据 xff0c 始终不会变化
  • Typora自动上传图片到Gitee图床

    Typora自动上传图片到Gitee图床 序言 思路 Gitee作为免费的图床 xff0c Typora作为最好用的blog博客笔记软件 xff0c 通过PicGo软件配置将Typora中的图片自动保存到Gitee图床 xff0c 获得云端
  • 关于百度OCR和EasyOCR的研究记录

    现行方案 xff1a 迅捷OCR软件 采用迅捷OCR文字识别软件 xff0c 购买了一年的期限 操作需要使用pyautogui来操作软件进行操作 xff0c 现在也可以使用USB鼠键模块KM3来真实模拟鼠标键盘的操作 xff0c 可信度更高
  • qt打开项目,只有pro文件其它文件消失:-1: error: msvc-version.conf loaded but QMAKE_MSC_VER isn‘t set

    之前在电脑打开开发的项目 xff0c 突然今天打开突然只有pro文件其它文件消失了 xff0c 在文件管理器里面找也都还有 打开项目只剩下蓝色框里面的 网上查了一些资料 xff0c 发现是开发程序事qt的版本不同所导致 解决方法 点开项目
  • 表格中重复项设置一级和二级序号排序

    摘要 xff1a 一级分类存在重复项 xff0c 需要排序 xff0c 二级分类也存在重复项 xff0c 也需要排序 xff0c 相同一级分类中的二级分类需要重新从一开始排序 xff08 重点和难点 xff09 先来看看效果 xff1a 公
  • 动态数码管显示实验

    文章目录 摘要实验器件简介实验原理硬件电路图硬件电路连线实验代码实验结果思考以及注意事项实验视频教程资源分享 摘要 本实验采用了普中科技的51单片机开发板 本实验以静态数码管显示实验为基础 https blog csdn net weixi
  • C51中intrins_h头文件解释分析

    文章目录 摘要源代码说明举个栗子 摘要 这是关于C51中使用循环移位等函数的头文件定义的分析 源代码 span class token comment INTRINS H Intrinsic functions for C51 Copyri
  • 喜马拉雅音频下载+x2m文件转换

    文章目录 摘要软件免费音频VIP音频 摘要 一款关于喜马拉雅音频的小神器 x2m格式转换为m4a格式 批量下载操作 软件 绿色免费的小工具ximalaya downloader amp x2m decoder xff0c 当然是在电脑上运行
  • http报错:405 (METHOD NOT ALLOWED)

    使用post请求ajax数据时 xff0c 报错 xff1a 405 METHOD NOT ALLOWED 将post请求改为get请求
  • Http怎么解决粘包拆包的?

    发送端 xff1a 应用层协议的每个包到达传输层 xff0c 如果是tcp xff0c 会可能出现以下情况 1 应用层的每个包被拆成多个tcp报文 xff0c 分别发送 xff0c 这是拆包 xff1b 2 应用层的多个包组成一个tcp报文
  • ROS TCP通信

    Reference https blog csdn net deyuzhi article details 51725074 https blog csdn net weixin 43795921 article details 85307
  • Ubuntu+ROS安装及rosdep init失败解决办法

    1 安装Ubuntu16 04 18 04 xff08 1 xff09 双系统硬盘安装 xff1a 参考双硬盘Window10与Ubuntu16 04 18 04安装 脚踩香蕉皮的博客 CSDN博客 Ubuntu 18 04 xff1a 链
  • c++ 编译 报错 未定义的引用

    遇到的问题有两种情况 一个是static没初始化 一个是模板类实现和定义分开写 这里主要记录一下模板类实现和定义分开写报错的问题 xff08 都放在 h文件中就不会报错 xff09 自己尝试用 传统 方法 xff0c 及在 h文件里声明 在
  • JNI基础语法

    一 Java和JNI类型对照 1 1 基本类型对照表 Java类型Native类型C C 43 43 类型大小Booleanjbooleanunsigned char无符号8位Bytejbytechar有符号8位Charjcharunsig
  • STL源码剖析 笔记之三 迭代器

    第三章 迭代器概念与traits编程技法 Design Patterns 中提供有23个设计模式的完整描述 迭代器模式定义如下 xff0c 提供一种方法 xff0c 使之能够依序巡防某个聚合物 容器 所含的各个元素 xff0c 而又无需暴露