迭代器是C++中非常重要的概念,是STL工具集中的重要一环。迭代器有很多类型,各自有其局限性。
-
输入迭代器:只能取指向的值,当迭代器自加后,之前指向的值就不可访问(不用此类迭代器在一个范围内遍历多次),典型的如std::istream_iterator。
-
前向迭代器:类似输入迭代器只能前进,但在指定范围内可迭代多次,典型的如std::forward_list(只能前向遍历,但可以反复迭代)。
-
输出迭代器:单纯用于写的迭代器,只能前进,且将内容写入对应容器(文件)中;读取的值是未定义的。

迭代器基础
每种容器都定义了自己的迭代器,可通过iterator获取(如vector::iterator)。通过begin与end函数可获取一对迭代器,表示范围(end不指向容器的任何元素,而是指向最后元素的下一个位置)以遍历容器元素。
vector<int> vec;
// ...
for(auto it=vec.begin(); it!=vec.end(); ++it){
cout<<*it<<endl;
}
// C++11
for(auto it:vec){
cout<<*it<<endl;
}
基本操作
迭代器可以像指针一样进行++与--操作,以及通过*解除引用,和比较操作等。此外还有三个函数模板:
-
advance(p,n):迭代器向前或向后(负数)移动n个元素;
-
distance(p,q):计算两个迭代器间的距离;
-
iter_swap(p,q):交换两个迭代器;
高级使用
迭代器与STL中的算法结合,可以产生强大的威力;通过插入迭代器,可方便插入数据至容器:
-
inserter(con,it):从容器con的it处开始插入
-
back_inserter(con):插入到容器尾部(需要容器支持push_back);
-
front_inserter(con):插入到容器头部(需要容器支持push_front);
通过copy输出容器内容:
template<typename T>
void toPrint(const T &con){
copy(begin(con),end(con), ostream_iterator<T::value_type>{count, ", "});
cout<<endl;
}
使用inserter创建容器
vector<int> vec{1,2,3,4,5};
deque<int> de;
copy_n(begin(vec), 3, inserter(de,begin(de))); // 从指定位置往后,依次插入内容
move(begin(vec),end(vec), front_inserter(de)); // 总是插入最前面,若是可移动类型(如string等)则vec中的内容将变为空
toPrint(de); // 5,4,3,2,1,1,2,3
算法中应用
在算法中会大量使用迭代器进行操作。
二分查找
对于已排序的容器,可通过查找算法获取对应位置迭代器:
-
binary_search(begin,end,foFind):查找到返回true,否则false;
-
equal_range(begin,end,foFind):返回一对迭代器(pair<lowerBound,UpperBound>),符合要求的元素为[lowerBound,UpperBound),若未查找到则lowerBound==UpperBound(即都指向符合要求元素插入的位置);
-
lower_bound(begin,end,foFind):返回第一个不小于(less)查找值的迭代器,若未找到返回end;
-
upper_bound(begin,end,foFind):返回大于查找值的第一个元素位置(即新元素插入位置);
排序
STL中有多个排序算法,满足不同用途:
-
sort:排序
-
stable_sort:稳定排序
-
partial_sort(first, middle, last):保证[first,middle)范围内容的元素是排序好的,且不大于后面的任何元素;
-
partition(first,last,pre):返回第一个不满足pre的迭代器it,保证[first,it)范围内元素满足pre,[it,last)范围内元素不满足pre;
-
nth_element(first, itN, last):把第N个元素放在位置N处,且前面的元素不大于它,后面的元素不小于它(但不排序);
vector<int> vec{1,2,3,4,5,6,7,8,9};
default_random_engine gbump;
shuffle(vec.begin(),vec.end(),g);
auto mid{next(vec.begin(), vec.size()/3)};
// partial_sort(vec.begin(), mid, vec.end()); // 保证前1/3元素有序
auto ret = parition(vec.begin(),vec.end(), [](auto i){return i<5}); // 所有小于5的排在前面,其他排在后面
cout *ret<<endl;
toPrint(vec);
创建迭代器
要实现一个前向迭代器,只需支持前缀加++,解引用*和比较操作!=即可(可用于enumeration-for语句中)。
class Num_iterator{
int m_cur=0;
public:
explicit Num_iterator{int nPos=0):m_cur(nPos){}
int operator*() {return m_cur;}
Num_iterator& operator++(){
++m_cur;
return *this;
}
Num_iterator& operator--(){
--m_cur;
return *this;
}
bool operator!=(const Num_iterator& other){
return m_cur != other.m_cur;
}
bool operator==(const Num_iterator& other){
return !operator!=(other);
}
};
为了使迭代器兼容STL算法,需要对标准模板进行特化:
template<>
struct iterator_traits<Num_iterator>{
using iterator_category = std::forward_iterator_tag;
using value_type = int;
using difference_type = int;
using pointer = const int*;
using reference = int;
}
}
有了迭代器,我们就可以定义自己的容器,如获取数字范围:
class Num_range{
int m_nStart=0;
int m_nEnd=0;
public:
Num_range{int from, int to):m_nStart(from), m_nEnd(to) {}
Num_iterator begin() const { return Num_iterator(m_nStart);}
Num_iterator end() const {return Num_iterator(m_nEnd);}
Num_iterator begin() { return Num_iterator(m_nStart);}
Num_iterator end() {return Num_iterator(m_nEnd);}
};
使用自定义容器:
Num_range rg(1, 10);
vector<int> vec;
transform(rg.begin(), rg.end(), back_inserter(vec), [](auto i) {return i*i;});
C++迭代器详解
2944

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



