IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【c++从菜鸡到王者】第八篇:深度剖析Traits技法 -> 正文阅读

[C++知识库]【c++从菜鸡到王者】第八篇:深度剖析Traits技法

Traits编程技法

  • Traits技法就是提取相应型别,什么是相应型别?迭代器所指对象的型别便是其中之一。(除此之外还有4中所必要的型别,后面详细介绍)
  • 在算法中我们要用到迭代器,假如一个算法需要使用迭代器中所指对象的型别来创建一个对象。就需要获取迭代器中的型别信息。我们知道每个容器都有专属的迭代器,所以每个容器的迭代器都含有我们所需要的相应的型别信息,所以需要一个特殊的装置帮我们提取相关的信息,那就是Traits(萃取机)

  • 下面我们具体介绍一下这5个型别的具体含义

    • value_type :指迭代器所指对象的型别

    • difference_type:用来表示两个迭代器之间的距离。因此它用来表示一个容器的最大容量

      typename iterator_traits<I>::difference_type;
      //任何时候我们需要迭代器I的difference_type 都可以这样写
      
    • reference_type、pointer_type :在c++函数中如果要传回左值(允许改变所指对象的内容),都是以by reference 的方式进行;就pointer_type而言,我们能够传回一个pointer,指向迭代器所指之物。

      Item& operator*()const{return *ptr;}
      Item* operator->()const{return ptr;}
      //Item&就是reference_type Iter*就是pointer_type
      
    • iterator_category:简单来说就是提取迭代器类型,为算法选择最有利于其功能的迭代器类型(迭代器类型有单向,双向,只读,只写,随机 迭代器)。

      • traits有能力提取迭代器的种类,我们利用其作为算法的一个参数,这个类别必须是class type,然后就能调用算法的不同形式,以提升效率
      //下面我将以advance()算法来描述这个类别
      //首先是5个用作标记的型别
      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();
      //下面是advance()算法的具体实现
      template<class InuputIterator,class Distance>
      inline void __advance(InputIterator& i,Distance n,input_iteratoo_tag){
          ...
      }
      template<class ForwardIterator,class Distance>
      inline void __advance( ForwardIterator& i,Distance n, forward_iterator_tag){
          ...
      }
      template<class BidirectionalIterator,class Distance>
      inline void __advance( BidirectionalIterator& i,Distance n, bidirectional_iterator_tag){
          ...
      }
      template<class RandomAccesslIterator,class Distance>
      inline void __advance( RandomAccesslIterator& i,Distance n, random_access_iterator_tag){
          ...
      }//以上函数的具体实现不同
      //每个__advance都只声明类别,不指定参数,只是纯粹用来激活重载机制的。
      

      这时我们需要准备一个上层接口,它只接受两个参数,当它把上述工作给__advance()时,才自行加上第三参数:迭代器类型。然后这个函数必须从迭代器中推导出类型。当然这个工作交traits。

      template<class InputIterator,class Distance>
      inline void advance(InputIterator &i,Distance n){
          __anvance(i,n,iterator_traits<InpurIterator>::iterator_category());
      }
      

      为了满足上述行为,traits必须还要增加一个相应的型别:iterator_category;

      template<class I>
      struct iterator_traits{
          ...
          typedef typename I::iterator_category iterator_category;
      };
      //另外还有两个偏特化版本,是针对原始指针设计而成,T*,const T*.他们的迭代器类型都是随机访问迭代器。
      
      • 注意:任何一个迭代器都应该落在"该迭代器隶属中"最强化的那一个。例如一个迭代器int*是上面的那5个迭代器类型,但是在程序中我们必须把它当作随机访问迭代器;

        STL算法的命名法则:以算法所能接受的最低阶迭代器类型,来为其迭代器类型命名。

      • 在上面我所列举的5个类型的型别定义中,后面3个为什么要公有继承前面的两个迭代器类型,为了消除“单纯传递调用的函数”,比如当客端调用distance()并使用Forward iterator时,统统都会调用Input iterator版的那个的__distance()。因为distance()算法里没有Forward iterator 版本。如果没有继承,我们就会在distance()的Forward版本里调用Input版本的。

  • iterator的保证

    • 为了规范,每个迭代器都要提供这5个类型。为了以防你初心,STL提供了一个iterator class 每个迭代器都可以继承它,以保证规范

      template<class Category,class T,class Distance=ptrdoff_t,class Pointer=T*,class Refrence=T&>
      struct iterator{
          typedef Category iterator_category;
          typedef T  value_type;
          typedef Distance difference_type;
          typedef Pointer pointer;
          typedef Reference reference;
      };
      //由于后面3个参数是默认的,所以我们在继承的时候必须指定前面的2个参数
      

总结:设计适当的型别是迭代器的责任,设计合适的迭代器是容器的责任,只有容器才知道设计出怎样的迭代器来遍历自己,并执行迭代器该执行的各种行为。至于算法完全独立于容器于迭代器,自行发展,只是设计时以迭代器为对外接口形式。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-27 16:01:53  更:2021-07-27 16:02:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 1:52:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码