STL标准模板库—迭代器部分【C++】

24 篇文章 2 订阅

STL迭代器

1、概念

迭代器,旨在提供一种方法,使得依次访问某容器内的各个元素,而又不需要暴露出该容器的内部表达方式。迭代器不是指针,是类模板,表现得像指针:迭代器返回额是对象引用而不是对象的值。

2、迭代器的几个型别
  • 值类型
  • 差值类型
  • 引用类型
  • 指针类型
  • 迭代器类型(包括单向迭代器、随即迭代器、双向迭代器)
    – [1] input_iterator;//只读迭代器
    – [2] output_interator;//只写迭代器
    – [3] Forward_iterator;//正向迭代器
    – [4] Bidirectional_iterator;//双向迭代器
    – [5] Random_Access_iterator;//随机迭代器
3、迭代器使用

以vector容器为例:

#include <iostream>
#include<vector>
using namespace std;

//模板函数
template<class _T>
void print(_T con)
{
	for(typename _T::const_iterator it=con.begin();it!=con.end();++it)
	{
		cout<<*it<<" ";
	}
	cout<<endl;
}

int main()
{
	//vector 随机迭代器
	vector<int> vec;
	for(int i=0;i<5;++i)
	{
		vec.push_back(i);
	} 
	//只能读取容器中的元素,不可修改
	vector<int>::const_iterator it=vec.begin();
	for( ; it!=vec.end();it++) 
	{
		cout<<*it<<" "; //    0 1 2 3 4 
	} 
	cout<<endl;
	
	vector<int>::iterator it2 =vec.begin();
	for( ; it2!=vec.end();++it2)
	{
		*it2=5;//使用 * 访问迭代器所指向的元素
		cout<<*it2<<" "; // 5 5 5 5 5
	} 
	cout<<endl;
	
	//迭代器的运算
	const vector<int>::iterator newiter=vec.begin();
	vector<int>::iterator newiter2=vec.end();
	cout<<newiter2-newiter<<endl;// 5
	
	//调用模板函数
	print(vec);
	return 0;
} 

迭代器的差值:

std::distance(start_id,end_it);//表示了元素个数
随机迭代器适用:直接相减,其他类型别的迭代器就需要逐个计数

4、迭代器失效问题
  • 对于顺序容器vector,deque来讲,在进行删除erase()操作后,后边的每个元素的迭代器都会失效,后边的每个元素都会往前移动,erase()返回下一个有效的迭代器。
  • 对于关联容器map,set来讲,进行删除erase()后,当前元素的迭代器失效,但因为其底层结构是红黑树,删除当前元素,并不会影响下一元素的迭代器,所以在调用erase()前,记录一下下一元素的迭代器即可。
  • 对于list,它使用了不连续的内存分配,并且其erase()也返回下一个有效的迭代器,因此,上面两种方式都可以。
5、迭代器的萃取

首先,先看看STL的迭代器的源码是怎么写的:

typedef int ptrdiffer_t;//差值类型
struct intput_iterator_tag{}; //只读迭代器
struct output_interator_tag{}; //可写迭代器
struct forward_iterator_tag{}; //正向迭代器
struct bidirection_iterator_tag{}; //随机迭代器

template<class _C, class _Ty, class _D = ptrdiff_t, class _Pointer = _Ty*,class _Reference = _Ty&>
struct iterator
{
	typedef _C            iterator_category;//迭代器的类型
	typedef _Ty                  value_type; //迭代器所迭代的数据的类型
	typedef _D              difference_type;//差值
	typedef _Pointer                pointer;//指针
	typedef _Reference            reference;//引用类型 
};

//类型萃取器
template<class _Iterator>
struct iterator_traits
{
	iterator_traits() {}
	typedef typename _Iterator::iterator_category iterator_category;
	typedef typename _Iterator::value_type        value_type;
	typedef typename _Iterator::difference_type   differce_type;
	typedef typename _Iterator::pointer           pointer;
	typedef typename _Iterator::reference         reference;
};

template<class T>
struct iterator_traits<T*>
{
	iterator_traits() {}
	typedef typename random_access_iterator_tag iterator_category;
	typedef typename T                          value_type;
	typedef typename int                        differce_type;
	typedef typename T *                        pointer;
	typedef typename T&                         reference;
};
template<class T>
struct iterator_traits<const T*>
{
	iterator_traits() {}
	typedef typename random_access_iterator_tag iterator_category;
	typedef typename T                          value_type;
	typedef typename int                        differce_type;
	typedef typename const T*                   pointer;
	typedef typename const T&                   reference;
};

/// SGI
template<class _II>
inline typename iterator_traits<_II>::iterator_category
iterator_category(const _II&)
{
	typedef typename iterator_traits<_II>::iterator_category cate;
	return cate();
}

template<class _II>
inline typename iterator_traits<_II>::value_type *
value_type(const _II&)
{
	return  static_cast<typename iterator_traits<_II>::value_type*>(0);
}

template<class _II>
inline typename iterator_traits<_II>::difference_type*
difference_type(const _II&)
{
	return static_cast<typename iterator_traits<_II>::difference_type*> (0);
}

// 正向迭代器
template<class _Ty, class _D = ptrdiff_t>
struct _Forit :public iterator<forward_iterator_tag, _Ty, _D> {};

// 双向迭代器
template<class _Ty,class _D = ptrdiff_t>
struct _Bidit :public iterator<bidirectional_iterator_tag,_Ty,_D>{};

// 随机迭代器
template<class _Ty,class _D = ptrdiff_t>
struct _Ranit :public iterator< random_access_iterator_tag, _Ty, _D> {};

template<class _II,class _D>
inline void __advance(_II& i, _D n, input_iterator_tag)
{
	while (n--)  ++i;
}

template<class _BI, class _D>
inline void __advance(_BI & i, _D n, bidirectional_iterator_tag)
{
	if (n >= 0)
	{
		while (n--) ++i;
	}
	else
	{
		while (n++) --i;
	}
}

template<class _RAI, class _D>
inline void __advance(_RAI& i, _D n, random_access_iterator_tag)
{
	i += n;
}

template<class _II,class _D>
inline void advance(_II& i, _D n)
{
	//iterator_traits<_II>();
	//typedef typename iterator_traits<_II>::iterator_category cate;
	__advance(i, n, iterator_category(i));
}
template<class _II>
inline typename iterator_traits<_II>::difference_type  
__distance(_II _F, _II _L, input_iterator_tag)
{
	typename iterator_traits<_II>::difference_type n = 0;
	while (_F != _L)
	{
		_F++;
		n++;
	}
	return n;
}
template<class _RAI>
inline typename iterator_traits<_RAI>::difference_type
__distance(_RAI _F, _RAI _L, random_access_iterator_tag)
{
	return _L - _F;
}

template<class _II>
inline typename iterator_traits<_II>::difference_type
distance(_II _F, _II _L)
{
	return __disstance(_F, _L, iterator_category(_F));
}

现在,来理解一下,迭代器是如何萃取到容器类型:

在这里插入图片描述
其实,从这里我们可以知道,迭代器的类型萃取是在编译时期就可以确定迭代器的类型了的。

之前我们还提到过,构造函数和析构函数的是否有关紧要,极大地影响了对象的创建与析构的代码的运行效率,所以用到类型萃取之后,编译器就会自动找到对应的函数来执行,以提高效率。

下一节:空间配置器...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值