迭代器iterator是C++ STL的六大组件之一,作用是用来遍历容器,而且是通用的遍历容器元素的方式,无论容器是基于什么数据结构实现的,尽管不同的数据结构,遍历元素的方式不一样,但是用迭代器遍历不同容器的代码是完全一样的。经典的迭代器遍历容器的代码如下:
vector<int>::iterator it = vec.begin();
for (; it != vec.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
unordered_set<int>::iterator it = us.begin();
for (; it != us.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
所示的迭代器都是依附于容器创建、使用的,除此之外其实也可以设计一种泛型的迭代器。实际上,C++11新标准的foreach语句,对于容器的遍历就是通过迭代器iterator实现的,如果容器没有实现iterator迭代器,那么foreach语句也无法遍历容器,上面vector容器的遍历代码可以简化为:
for (int val : vec) // 实际上是用迭代器遍历容器vec
{
cout << val << " ";
}
cout << endl;
迭代器一般实现为容器的嵌套类型,在容器内部提供具体的实现。但是容器不同,底层元素遍历的方式也不同,那么为什么说迭代器遍历所有容器的方式是一样的呢?那是因为迭代器提供了常用的operator!=,operator++,operator*等运算符的重载函数,把迭代容器的细节全部隐藏在这些通用的运算符重载函数里面,因此用户侧表现出来的就是,迭代器遍历所有容器的方式都是一样的,其实底层都是不一样。所以刚开始的那个问题就可以回答了,泛型算法是针对很多容器实现的通用算法,肯定需要一种统一的方式遍历容器的元素,只有迭代器才能做到!
迭代器实现原理
迭代器提供了常用的operator!=,operator++,operator*等运算符的重载函数,把迭代容器的细节全部隐藏在这些通用的运算符重载函数里面。
这部分提供一个极简的vector容器实现,然后给它提供一个迭代器iterator的实现,看看容器迭代器的原理是什么,这里面容器的空间配置器直接使用C++标准库的allocator默认实现。
#include <iostream>
// 简单的vector容器实现,主要查看其嵌套类iterator迭代器的实现
template<typename T,
typename Alloc = std::allocator<T>>
class MyVector
{
public:
MyVector(const Alloc &alloc = Alloc())
:_allocator(alloc)
{
_first._ptr = _last._ptr = _end._ptr = nullptr;
}
template<typename T>
void push_back(T &&val)
{
if (full())
resize();
_allocator.construct(_last._ptr, std::forward<T>(val));
_last._ptr++;
}
void pop_back()
{
if (empty())
return;
_last._ptr--;
_allocator.destroy(_last._ptr);
}
bool full()const { return _last._ptr == _end._ptr; }
bool empty()const { return _first._ptr == _last._ptr; }
// 容器迭代器的实现
class iterator
{
public:
friend class MyVector;
iterator(T *ptr = nullptr)
:_ptr(ptr) {}
void operator++() { ++_ptr; }
bool operator!=(const iterator &it) { return _ptr != it._ptr; }
T& operator*() { return *_ptr; }
T* operator->() { return _ptr; }
private:
T *_ptr;
};
// 容器的begin方法返回首元素迭代器
iterator begin() { return iterator(_first._ptr); }
// 容器的end方法返回末尾元素后继位置的迭代器
iterator end() { return iterator(_last._ptr); }
private:
iterator _first; // 指向数组其实地址
iterator _last; // 指向最后一个有效元素的后继位置
iterator _end; // 指向数据空间末尾元素的后

最低0.47元/天 解锁文章
739

被折叠的 条评论
为什么被折叠?



