关于迭代器(iterator)和指针的思考
2012-11-11 17:53
351 查看
今天有点闲,于是打开电子版的<<C++ PRIMER 4TH>>来看。其中9.2节有一个表9.4,它指出了vector 和 deque 类型迭代器支持的操作。这本来是很平常的,但是表中的iter1+iter2引起了我极大的兴趣。于是写了下面一段代码来验证是否真的能支持这运算
#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 Snippet
template<class Iter>
void display(Iter begin, Iter end)
{
Iter it=begin;
while(++it!=end)
cout<<*it<<" ";
cout<<endl;
}
当然你也可以使用Reverse_Iterator来进行反向的遍历。当时Reverse_Iterator和Iterator所指向的位置差一个元素。需要注意。
#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 Snippet
template<class Iter>
void display(Iter begin, Iter end)
{
Iter it=begin;
while(++it!=end)
cout<<*it<<" ";
cout<<endl;
}
当然你也可以使用Reverse_Iterator来进行反向的遍历。当时Reverse_Iterator和Iterator所指向的位置差一个元素。需要注意。
相关文章推荐
- 关于迭代器(iterator)和指针的思考
- 关于迭代器(iterator)和指针的思考
- 关于Iterator探究和思考
- 关于C语言中函数值传递的巩固,指向指针的指针 【网络编程获取借口列表时,使用了指针的指针的思考】
- [BS-21] 关于OC中对象与指针的思考
- 关于c++中一些指针问题的思考
- 关于类成员变量为引用与指针的思考
- 关于指针的思考与理解
- 关于空指针问题思考
- 关于STL的list,vector等用迭代器iterator,用erase删除元素出现的问题。
- 关于基类和派生类之间的指针混合的思考
- 关于Iterator会报空指针的方法
- 关于Iterator接口(迭代器)
- 关于C语言的指针传递地址的一些思考
- 关于Iterator探究和思考
- unsigned short *Sum( unsigned char a,unsigned char b);关于指针的一些思考
- 由一道PHP笔试题引发的思考(关于php5的Iterator接口)
- 关于 Python Iterator 协议的一点思考
- 关于指针与类的内存分布问题(问题思考来自《程序员面试宝典》)
- Java中关于Iterator和Iteratable设计的思考