STL(二):Iterator

本文探讨STL中Iterator的重要角色,它作为算法和容器之间的桥梁。介绍五种Iterator类型及其继承关系,并展示了如何在vector和自定义容器中使用Iterator。此外,还提及了已废弃的auto_ptr以及简单的iterator使用示例。
摘要由CSDN通过智能技术生成

前言

STL的algorithm包含了各种算法的实现,这些算法必须能对不同的容器和容器的适配器进行操作,比如下面的例子:

#include <bits/stdc++.h>
using namespace std;

int main(){
    vector<int> m_vec{1, 3, 2, 4};
    deque<int> m_deque{1, 3, 2, 4};
    sort(m_vec.begin(), m_vec.end());
    sort(m_deque.begin(), m_deque.end());
    return 0;
}

对于上面代码中的两个sort,如果通过函数重载来实现对不同容器类型的排序,用户自定义需要考虑的问题增加了很多,不利于STL的扩展。为此,STL提供了Iterator作为将算法和容器连接起来的桥梁,下面我们来看看iterator相关的源码,同样的,代码会在最后给出。

Iterator类型

STL提供类5中类型的Iterator

  • input_iterator :用于读取所指向元素的输入
  • output_iterator:用于向所指向元素写入
  • forward_iterator:可前向移动的可读取指向元素的迭代器
  • bidirectional_iterator:可双向移动的可读取指向元素的迭代器
  • random_access_iterator:可双向移动的,能在常数时间内移动到任意元素的可读迭代器
    他们之间具有如下继承关系:
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 {};

对于用户自定义的iterator,最好需要继承std::iterator,其中包含了STL需要的五种类型,保证容器在自定义类型中的使用。

// 用户自己的写的迭代器最好继承此 std::iterator
#ifdef __STL_USE_NAMESPACES
template <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;
};
#endif /* __STL_USE_NAMESPACES */

iterator可以看作进化的指针,以vector为例,我们来看看与iterator相关的代码:

template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
class vector : protected _Vector_base<_Tp, _Alloc> 
{
public:
  typedef _Tp value_type;
  typedef value_type* iterator; // vector 的迭代器
  typedef const value_type* const_iterator;
}

可以发现,假如我们声明vector<int>,_Tp就为int,iterator的类型为int*,即一个普通指针。STL还实现了一个基于vector的位图,称为bvector,bvector的迭代器就相对复杂的多,在下面的代码中可以看到bvector迭代器的继承路径。与vector的迭代器不同,_Bit_iterator不是通过指针类型被使用,但为了模仿指针的行为,_Bit_iterator重载了operator*/operator&/operator->,以匹配指针的行为。

struct _Bit_iterator_base : public random_access_iterator<bool, ptrdiff_t> 

struct _Bit_iterator : public _Bit_iterator_base

不同的容器通过继承不同的iterator类型,可能具有不同特性的iterator,每种容器的iterator将在介绍容器时介绍,但不管是哪种iterator,都必须具有下面5种元素类型。

  • iterator_category:迭代器类别;
  • value_type:迭代器解引用后的值的类型;
  • difference_type:两个迭代器之间的距离;
  • pointer:被迭代类型的指针;
  • reference:被迭代类型的引用;

auto_ptr

在SGI的memory.h文件中,介绍了auto_ptr,但auto_ptr已被废弃,取而代之的是另外三种智能指针,可在c++11智能指针中查看相关特性。

iterator使用

最后给出一个通过iterator遍历vector的简单使用代码:

#include <bits/stdc++.h>

int main(){
	std::vector<int> nums = {1, 2, 3, 4};
	std::vector<int>::iterator it = nums.begin();   //c++11以后,可以直接写成auto it = nums.begin();
	for(;it != nums.end();++it){
		std::cout << *it << std::endl;
	}    
	return 0;
}

nums.begin()将返回指向nums第一个元素的迭代器,而nums.end()并不指向任何元素,这是一个在容器元素末尾的哨兵,当访问到nums.end()时,说明已经完成遍历。

SGI STL源码

iterator相关源码:iterator

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值