stl源码剖析(3)迭代器和traits

迭代器

STL的中心思想是:将数据容器和算法分隔开,彼此独立设计,最后再用黏合剂将它们撮合在一起。容器和算法的泛型化,可以用C++的class template和function template来实现,而二者的黏合剂就是迭代器了。

STL将迭代器的实现交给了容器,每种容器都会以嵌套的方式在内部定义专属的迭代器。各种迭代器的接口相同,内部实现却不相同。

迭代器实际上就是一个封装了指针的类模板,类似于智能指针,定义在每个容器类模板里面,所有的迭代器都重载了指针的一些基本操作如*、->、++、==、!=,还有一些根据它的迭代器种类,重载的指针运算符 ++ -- += 等等,里面还typedef了一些别的信息,然后泛型算法通过重载工具函数,还有一个通用的接口函数,实现在编译期决定调用哪个工具函数,使得泛型算法的效率得到提升。

其实我看了 stl_list和stl_vector的源码,vector里面干脆用的是就是原生指针 T *,而list里面 迭代器也不是定义在class list里面,而是在list外面,定义了一个struct  __list_iterator 模板,而且在class list里面有个typedef __list_iterator<T, T&, T*>             iterator;

并且iterator里面也没有 typedef T value_type; 反而是定义在list里面,anyway,反正都差不多。

迭代器有以下5种类型

input    只能向前移动 只读 所指物只能读取一次
output   只能向前移动 只写 所指物只能写一次 
forward  只能向前移动 可读写 所指物能读写多次
bidirectional 能双向移动 可读写 所指物能读写多次
random access 能跳着移动 可读写 所指物能读写多次  注意 原生指针正是这种类型
c++ 定义了 5种struct 分别对应上面的 并且 除了output 下面的迭代器 继承上面的迭代器  (effective cpp p228)


traits

1.    总结:


利用内嵌型别(typedef)和编译器template参数推导功能,获取某些类型信息
加一个中间层 iterator_traits  并且运用模板偏特化技术 实现让原生指针也是一种迭代器的问题
运用重载实现函数和,统一了接口函数,再加上用迭代器的种类变为一个类,也就是使用对象(假如使用函数,那就会是在运行期才会决定调用哪个重载函数 maybe 我猜的),实现在编译期获得信息,决断具体调用哪个函数的能力。

最终的目的就是为了根据获得的类型信息 提升泛型算法的效率!


2.    详细:


traits就像一个萃取机一样,去榨取特征
允许你在编译期间取得某些类型信息,并且对于内置类型(如指针)和用户自定义类型的表现一样好。
它的目的是 比如迭代器trait,我们可以根据迭代器的某些类型信息(并且可以在编译期就获得,而不用typeid,在运行期再决定),对于同一个泛型算法,能够根据这些类型信息做不同的操作,比如一个算法要求 iterator 前进n步,对于一般的迭代器只能一次一次+1,但是对于random access可以一次+n,算法的效率就更高。
为什么要加个traits类,主要就是为了解决原生指针也是种迭代器的问题,不然直接在用户自定义类型里面typedef 内嵌型别就ok了
对于 iterator_traits的实现方式:对于用户自定义类型 也就是iterator类型,在定义迭代器的时候(每一种容器有自己的迭代器类型,所以迭代器是定义在容器定义里面的,也就是实现形式是内嵌类)
 typedef xx_tag iterator_category ( xx_tag 也是个struct 就是迭代器的分类),然后在定义一个iterator_traits<typename iter>的类模板,在里面再
typedef typename iter:: iterator_category iterator_category 
而对于内置类型,也就是指针, 对iterator_traits 进行一个偏特化,也就是
iterator_traits< iter *>和 iterator_traits<const iter *>
在定义迭代器里面我们要typedef 5种类型信息:
1)    value_type
2)    iterator_category
3)    difference_type
4)    pointer
5)    reference

用法举例 iterator_traits<iter>::difference_type 
 

另外还有type_traits,在c++11里面,好像获得了支持,我看侯捷说的,但是一些简单的is_void这些简单的traits实现细节跟iterator的5个traits思想是一样的,但是复杂的如is_pod,is_trivial_xx 这些怎么实现的 源码没有,maybe是编译器参与的功劳。

 

另附参考:虽然我觉得写的不好,我也没看过,但假如以后2刷的时候,可以看看

https://blog.csdn.net/wutao1530663/article/details/64922389

https://blog.csdn.net/imxiangzi/article/details/49836559

https://zhuanlan.zhihu.com/p/51999289

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STL实现迭代器萃取的方式是通过对iterator_traits进行偏特化。为了使迭代器萃取有效运行,每个迭代器都要自行以内嵌性别定义的方式定义出相应的型别。迭代器的类型萃取机制被定义为iterator_traits模板类,它接受一个迭代器类型作为模板参数,并通过特化来提取迭代器的相关信息。 在STL中,对于一般的迭代器类型,使用iterator_traits模板类进行萃取,通过迭代器的内嵌typedef来获取iterator_category、value_type、difference_type、pointer和reference等相应的型别。而针对原生指针类型的迭代器STL会针对指针类型进行偏特化,直接定义出相应的型别,如random_access_iterator_tag、_Tp、ptrdiff_t、_Tp*和_Tp&等。这样就可以实现对迭代器的属性萃取。 通过对iterator_traits进行偏特化,STL能够根据不同的迭代器类型提取出相应的属性,从而能够在算法中正确地使用不同类型的迭代器,并根据迭代器的属性进行相应的操作。这样实现了迭代器的通用性和灵活性,使得STL算法可以适用于不同类型的迭代器。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [STL迭代器---萃取](https://blog.csdn.net/jiewaikexue/article/details/111372288)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [STL 迭代器萃取](https://blog.csdn.net/qq_40080842/article/details/128112675)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值