迭代器是什么
迭代器是指向元素范围(如数组或容器)中的某个元素的任何对象,它能够使用一组运算符(至少包括++和&运算符)遍历该范围的元素。
迭代器最明显的形式是指针:指针可以指向数组中的元素,并可以使用++循环访问它们。每个容器类型都有一个特定的迭代器类型,用于循环访问其元素。
迭代器一般实现为容器的嵌套类型,在容器内部提供具体的实现。但是容器不同,底层元素遍历的方式也不同,迭代器提供常用的operator!=,operator++,operator*等运算符的重载函数,将迭代器封装在运算符重载中,在用户端的使用方式上是一致的,但是底层的实现方式并不相同
迭代器按照定义分为以下四种
1) 正向迭代器
容器类名::iterator 迭代器名;
2) 常量正向迭代器
容器类名::const_iterator 迭代器名;
3) 反向迭代器
容器类名::reverse_iterator 迭代器名;
4) 常量反向迭代器
容器类名::const_reverse_iterator 迭代器名;
迭代器作用
通过迭代器可以读取它指向的元素,*迭代器名
就表示迭代器指向的元素。通过非常量迭代器还能修改其指向的元素。
迭代器都可以进行++
操作。反向迭代器和正向迭代器的区别在于:
- 对正向迭代器进行
++
操作时,迭代器会指向容器中的后一个元素; - 而对反向迭代器进行
++
操作时,迭代器会指向容器中的前一个元素。
void test_3()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(3);
v1.push_back(5);
v1.push_back(7);
v1.push_back(9);
vector<int>::iterator it = v1.begin();//正向迭代器
while (it != v1.end())
{
cout << *it << " ";
it++;
}
cout << endl;
auto rit = v1.rbegin();//反向迭代器
while (rit != v1.rend())
{
cout << *rit << " ";
rit++;
}
cout << endl;
}
常量迭代器与普通迭代器区分
1.typedef T* iterator;
2.typedef const iterator const_iterator;
3.typedef const T* const_iterator;
方式1 | 方式2 | 方式3 |
说明迭代器的本质上是一个指针 | 相当于T* const。const修饰iterator,说明iterator本身不可被修改,迭代器指向的内容可以被修改 | const修饰T*,说明指针指向的内容不可以被修改,但是迭代器还是可以进行++等操作 |
因此普通迭代器的实现用方式1实现,常迭代器用方式3实现。
方式二的实现方式是错误的
反向迭代器
正向迭代器与反向迭代器的并没有很大的区别,区别在于++、--的反向不同
//迭代器是原生指针或者是自定义类型
//普通迭代器类
template<class T,class Ref,class Ptr>
//Ref与Ptr是为了适用常量迭代器,Ref=T& Ptr=T*
struct __list_iterator
{
typedef list_node<T> node;
typedef __list_iterator<T,Ref,Ptr> self;//类对象本身
node* _node;
__list_iterator(node* n)//迭代器初始化
:_node(n)
{}
Ref operator* ()
//常量迭代器与普通迭代器只有返回值不同
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
self& operator++()//返回迭代器类对象
{
_node = _node->_next;
return *this;
}
self& operator++(int)//int只用于标识后置++
{
self tmp(*this);
_node = _node->_next;
return tmp;
}
self& operator--()
{
_node = _node->_prev;
return *this;
}
self& operator--(int)
{
self tmp(*this);
_node = _node->_prev;
return tmp;
}
bool operator!=(const self& li)
{
return _node != li._node;
}
bool operator==(const self& li)
{
return _node == li._node;
}
};
typedef __list_iterator<T, const T&, const T*>reverse_iterator;//反向迭代器
reverse_iterator rbegin () { return reverse_iterator(_head->_prev); }
reverse_iterator rend() { return reverse_iterator(_head); }
对于如上的代码
STL库中尽可能使得代码简洁高效,因此会将正向迭代器和反向迭代器设计的尽可能相像
因此需要模拟实现反向迭代器,下面以list容器为例
#pragma once
namespace my_iterator
{
template<class Iterator,class Ref,class Ptr>
struct ReverseIterator
{
typedef ReverseIterator<Iterator,Ref,Ptr> Self;
Iterator _cur;
ReverseIterator(Iterator it)
:_cur(it)
{
}
Ref operator*()
{
Iterator tmp = _cur;//由于是反向得,因此是正向迭代器对应得前一个位置
--tmp;
return *tmp;
}
Self& operator++()
{
--_cur;
return *this;
}
Self& operator++(int)
{
--_cur;
return *this;
}
Self& operator--()
{
++_cur;
return *this;
}
Self& operator--(int)
{
++_cur;
return *this;
}
bool operator!=(const Self& s)
{
return _cur != s._cur;
}
};
}
typedef ReverseIterator<iterator, T&, T*>reverse_iterator;//反向迭代器
typedef ReverseIterator<iterator, const T&, const T*> const_reverse_iterator;//反向迭代器
reverse_iterator rbegin () { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }