STL迭代器之迭代器绑定器:Iterator Traits

Iterators有不同的类型,每种类型都代表着不同的能力,它在重载某个行为时,是有用的,甚至有必要。通过iterators tags和iterator traits 重载可以实现。对于么一个iterator类型STL都提供一个 terator tag ,这个 terator tag 能被做一个 ’table”.
namespace std {
struct output_iterator_tag {
};
struct input_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 {
};
}
如果要写一个泛型代码,你也许不仅需要iterator category ,例如你可能需要迭代器引用的类型,所以STL提供了一个特殊的面板结构体来定义iterator traits ,这个结构体包含了所有关于an iterator 的信息。它被用于定义一个iterator类型的正常的接口。 
namespace std {
template <class T>
struct iterator_traits {
typedef typename T::value_type value_type;
typedef typename T::difference_type difference_type;
typedef typename T::iterator_category iterator_category;
typedef typename T::pointer pointer;
typedef typename T::reference reference;
};
}
这个结构体的模板参数是 iterator.
这个结构体有两个有点:
1.         它保证一个 iterator 提供了所有的类型定义。
2.         它能被特殊的迭代器特化或部分特化。
例如
namespace std {
template <class T>
struct iterator_traits<T*> {
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef random_access_iterator_tag iterator_category;
typedef T* pointer;
typedef T& reference;
};
}
因此对于任何指向 T 的指针类型,它都是 random access iterator  种类。

怎么写一个泛型函数。
如果你写泛型函数没有用到 iterator_traits ,它的实现很简单。例如:
template <class OutPutIterator>
void display(OutPutIterator start,OutPutIterator end)
{
    while(start!=end)
         {
                   cout<<*start<<" ";
                   ++start;
         }
         cout<<endl;
}
这个使用于任何顺序容器。

但有的时候能用到,为了不同 iterator 种类,你一定要有以下两步:
Step 1. 让你的模板函数调用另一个函数,该函数增加了一个iterator category参数。
例如:
template <class Iterator>
inline void foo (Iterator beg, Iterator end)
{
foo (beg, end,std::iterator_traits<Iterator>::iterator_category());
}





Step2
为每一个 iterator 种类实现一个函数实现:
template <class BiIterator>
void foo (BiIterator beg, BiIterator end,
std::bidirectional_iterator_tag)
{
...
}
//foo() for random access iterators
template <class RaIterator>
void foo (RaIterator beg, RaIterator end,
std::random_access_iterator_tag)
{
}

看下 advance() 函数的实现过程。
template <class Iterator>
typename std::iterator_traits<Iterator>::difference_type
distance (Iterator pos1, Iterator pos2)
{
return distance (pos1, pos2,std::iterator_traits<Iterator>::iterator_category());
}
//distance() for random access iterators
template <class RaIterator>
typename std::iterator_traits<RaIterator>::difference_type
distance (RaIterator pos1, RaIterator pos2,
std::random_access_iterator_tag)
{
return pos2 - pos1;
}
//distance() for input, forward, and bidirectional iterators
template <class InIterator>
typename std::iterator_traits<lnIterator>::difference_type
distance (Inlterator pos1, InIterator pos2,
std::input_iterator_tag)
{
typename std::iterator_traits<lnIterator>::difference_type d;
for (d=0; pos1 != pos2; ++pos1, ++d) {
;
}
return d;
}


如何定义一个 iterator
在定义自己的 iterator 时,你需要提供iterator traits。
有两种方法;
1.       提供必要的 iterator_traits 的五种类型。
2.       提供 iterator_traits 结构体的特化。
对于第一种方法, STL 提供了一个基类 iteratoe<>, 它用于类型的定义。你可以这样:
class MyIterator
: public std::iterator <std::bidirectional_iterator_tag,
type, ptrdiff_t, type*, type&> {
...
};
第一个参数是the iterator category, 第二个参数是元素类型type,第三个是差值类型(difference type),第四个是指针类型(pointer type),第五个是引用类型(reference type),最后三个是可选的,它们默认的类型: ptrdif_f_t,  type *,  and  type &
### C++ STL 迭代器构造方法与原理 #### 迭代器的概念及其重要性 迭代器是C++标准模板库(STL)中的一个重要概念,用于遍历容器中的元素。通过抽象化指针操作,迭代器使得算法能够独立于具体的容器类型工作。 #### 迭代器的实现方式 迭代器通常被设计成类模板的形式来支持多种数据结构。对于内置数组或者连续内存存储的数据结构(如`vector`)来说,迭代器内部实际上就是一个指向该种数据类型的指针[^1]。而对于链表这样的非连续存储结构,则会更加复杂一些,因为它们不仅需要保存当前节点的位置信息,还可能涉及到前后节点的信息维护。 #### 不同种类迭代器的特点 根据不同的需求场景,STL定义了几种不同级别的迭代器接口: - **输入迭代器(Input Iterator)**:只读访问单向序列; - **输出迭代器(Output Iterator)**:仅限写入操作; - **前向迭代器(Forward Iterator)**:可重复读取已访问过的值并允许多次遍历同一集合; - **双向迭代器(Bidirectional Iterator)**:除了具备前向迭代器的能力外还能反方向移动; - **随机存取迭代器(Random Access Iterator)**:提供类似于指针的操作能力,比如可以直接跳跃到任意位置[^4]; 这些特性决定了哪些特定类型的算法可以应用于相应的迭代器之上。 #### 类型特征萃取机制的作用 为了使某些通用组件能够在不知道具体类型的情况下做出最优决策,C++引入了一套名为__type_traits__ 的工具集。这其中包括但不限于判断某个给定类型是否有默认构造函数、拷贝构造函数等基本性质的方法[^3]。当创建自定义迭代器时,合理利用这类元编程技术可以帮助优化性能表现。 #### 使用建议 考虑到效率问题,在编写涉及频繁增减索引变量的应用程序部分时,推荐优先采用前置增量(`++it`)而非后置版本(`it++`),因为在后者情况下编译器不得不额外创建临时副本以保留原始状态供后续使用。 ```cpp std::vector<int> numbers = {1, 2, 3}; auto it = numbers.begin(); while (it != numbers.end()) { std::cout << *it << ' '; ++it; // 推荐的做法 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值