#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> vec(10);
vector<int>::iterator iter1=vec.begin();
vector<int>::iterator iter2=vec.end();
iter1+=iter2;
return 0;
}
使用MINGW和g++进行编译,结果报错,错误信息如下:
candidates are: __gnu_cxx::__normal_iterator<_Iterator, _Container>& __gnu_cxx::__normal_iterator<_Iterator, _Container>::operator+=(const typename std::iterator_traits<_Iterator>::difference_type&) [with _Iterator = int*, _Container = std::vector<int, std::allocator<int> >]
这也就是说在头文件中根本就没有为iterator进行+= iter,iter1+iter2运算符的重载。进过测试之后发现-=符号也报同样的错。至于iter + n ,iter – n,iter1 - iter2,这三种运算是没有任何编译问题的。也许是因为编译器的问题吧,但是实验到了这里,我不由得开始思考到底iterator和指针到底有怎么样的联系和区别,
经过思考,我得出了下面几个相同的地方:
1. 指针和iterator都支持与整数进行+,-运算,而且其含义都是从当前位置向前或者向后移动n个位置
2. 指针和iterator都支持减法运算,指针-指针得到的是两个指针之间的距离,迭代器-迭代器得到的是两个迭代器之间的距离
3. 通过指针或者iterator都能够修改其指向的元素
通过上面这几点看,两者真的很像,但是两者也有着下面的几个不同地方
1. cout操作符可以直接输出指针的值,但是对迭代器进行在操作的时候会报错。通过看报错信息和头文件知道,迭代器返回的是对象引用而不是对象的值,所以cout只能输出迭代器使用*取值后的值而不能直接输出其自身。
2. 指针能指向函数而迭代器不行,迭代器只能指向容器
这就说明了迭代器和指针其实是完全不一样的概念来的。指针是一种特殊的变量,它专门用来存放另一变量的地址,而迭代器只是参考了指针的特性进行设计的一种STL接口。
笔者曾在网上看到这样一种说法:迭代器是广义指针,而指针满足所有迭代器要求。迭代器是STL算法的接口,而指针是迭代器,因此STL算法可以使用指针来对基于指针的非STL容器进行操作。
笔者觉得上面说法也有几分道理,但是到底正不正确就留给看官自己判断了。但是有一点希望大家注意的是:千万不要把指针和迭代器搞混了。也许某些编译器使用指针来实现迭代器以至于有些人会误以为指针和迭代器是一个概念来的。
PS:《C++ PRIMER 4TH》表9.4有误,希望各位看官在看那本书的时候注意一下。
C++容器迭代器类的自动提供越界检查本来是个好东西,但不如指针方便,尤其是在循环判断时,我们有时写函数时为了用户方便形参必须使用迭代器,如下面代码
template<class Iter>
void display(Iter begin, Iter end)
{
Iter it=end;
while(--it!=begin)
cout<<*it<<" ";
cout<<endl;
}
这段代码若用指针一点问题没有,但若用迭代器,在循环结束时it应该<begin,但迭代器类会自动检查越界而出现运行时错误。我们如何才能在开始时将形参迭代器转为指针?
你好,
Iterator并不是普通的指针,可以说是智能指针。只有在vector容器中Iterator才是普通的指针。其他情况Iterator都是比较复杂的数据就够。Iterator分为了只读、只写、向前、双向和随机访问五种不同的类型。根据容器的不同和使用的情况,Iterator使用不同的类型。像List就是双向的Iterator。
所有的Iterator都符合左闭右开的原则。所以你可以使用一下方式遍历容器。因为end指向容器中最后元素后面的空位置。
Code Snippettemplate<class Iter>
void display(Iter begin, Iter end)
{
Iter it=begin;
while(++it!=end)
cout<<*it<<" ";
cout<<endl;
}
当然你也可以使用Reverse_Iterator来进行反向的遍历。当时Reverse_Iterator和Iterator所指向的位置差一个元素。需要注意。