STL之迭代器基本概念 [转贴]

STL是C++中重要部分之一(面向对象、STL、模板等),其中三个基本的STL组件包括:
1. 迭代器。迭代器之于容器相当于指针之于数组,提供了访问容器对象的方法,事实上C++中的指针也是一种迭代器,但是要注意迭代器不仅仅是指针,不一定具有地址值。
2. 容器。容器是一种模板类,例如list、vector、deques等,一般由迭代器访问容器中的数据。
3. 算法。STL中数据结构和算法是分离的,各种函数在广义容器中(包括链表、数组、string对象、容器)完全通用。

1.头文件:
STL头文件一般不使用.h扩展,其中主要使用的头文件和对应容器类如下:
#include Container Class
<deque> deque
<list>  list
<map>  map, multimap
<queue> queue, priority_queue
<set>  set, multiset
<stack> stack
<vector> vector
<string>  string
<iterator> ***<***>::iterator
<algorithm> 各种算法函数
STL均使用标准命名空间using namespace std。

2.迭代器:
迭代器有五种类型,这五种类型是一种继承关系,具体如下:
Input iterators:提供对数据的只读访问,前向推进。输入迭代器可以使用==和!=来测试是否相等;使用*来访问数据;使用++操作符前向推进。例如find函数需要保证输入迭代器。
Output iterators:提供对数据的只写访问,前向推进。输出迭代器缺省只写,由于该迭代器无法读取对象,因此不会在任何搜索和其他算法中使用它。
Forward iterators:提供读写访问,前向推进。例如replace函数需要保证前向迭代器。
Bidirectional iterators:提供读写访问,前向或后向推进。例如reverse函数需要保证双向迭代器。
Random access iterators:提供读写访问,随机移动(非const的指针也是随机迭代器)。STL中的排序和搜索函数使用随机访问迭代器,随机访问迭代器可以使用关系操作符做比较。
除此之外,还包括一些特殊的迭代器:
指针迭代器:一个指针也是一种迭代器。
常量迭代器:对于只读变量,为了防止错误赋值,可以使用常量迭代器const_iterator,该迭代器指向的对象不允许改变。注意:const ***<***>::iterator的含义是该迭代器成为常量,不可指向其他数据,与常量迭代器的含义是不一样的。

3.流迭代器
将输入输出(例如标准输入输出流cin/cout或者文件流等)作为容器看待,因此接受迭代器参数的算法都可以和流一起工作。
STL定义模板类ostream_iterator作为输出流迭代器,其构造函数有两个参数,包括一个ostream对象和一个string值(作为间隔符),因此可以象下面一样创建一个迭代器:
ostream_iterator<int>(cout, “/t”)             //定义cout迭代器
ofstream out(“text.txt”);
ostream_iterator<string> obegin(out, “/n”);       //定义文件流输出迭代器
STL定义模板类istream_iterator作为输入流迭代器,可指定读取的来源,并应该和结束迭代器比较。具体如下:
istream_iterator<int> intreader(cin);       //定义cin流迭代器
isteam_iterator<int> eof;
copy(istream_iterator<string>(cin), istream_iterator<string>(), 输出迭代器);      //定义无变量名的cin流迭代器
ifstream in(“text.txt”);
istream_iterator<string> ibegin(in);
istream_iterator<string> iend;            //定义文件流输入迭代器
还有一些具体应用如下:

// 利用流迭代器填充vector
{
    ifstream 
in("test.txt");
    istream_iterator
<string> ibegin(in);
    istream_iterator
<string> iend;
    vector
<string> vec(ibegin, iend);
    copy(vec.begin(), vec.end(), ostream_iterator
<string>(cout, "/n"));
}

// 利用输入流填充vector
{
    vector
<string> vec;
    copy(istream_iterator
<string>(cin), istream_iterator<string>(), back_inserter(vec));
    sort(vec.begin(), vec.end());
    copy(vec.begin(), vec.end(), ostream_iterator
<string>(cout,"/n"));
}

// 利用流迭代器保存vector内容到文件
{
    ifstream 
in("test.txt");
    istream_iterator
<string> ibegin(in);
    istream_iterator
<string> iend;
    vector
<string> vec(ibegin, iend);
    ofstream 
out("testcopy.txt");
    copy(vec.begin(), vec.end(), ostream_iterator
<string>(out"/n"));    
}

注意:上面用输入流迭代器来初始化vector后,不可再用这个输入流迭代器,因为随着数据的读取,迭代器已经到达输入流或者文件流的末尾了。

4.插入迭代器:
int arr[] = {1, 2, 3, 4, 5};
vector<int> vi;
copy(arr, arr + 5; vi.begin());
该语句不会执行,因为没有为vi分配存储空间。此时使用插入迭代器可以将值插入到容器中,自动为vi扩展存储空间,主要包括三种插入迭代器。
普通插入器:将对象插入到容器任何对象的前面。该迭代器使用容器的insert操作符替代赋值运算符,第一个参数是容器本身,第二个参数是容器迭代器指定插入位置。
Front inserters:将对象插入到数据集的前面,例如链表表头。该迭代器使用push_front操作替代赋值运算符,参数是容器本身。
Back inserters:将对象插入到数据集的尾部,例如vector的尾部,导致vector容器扩展。该迭代器调用容器的push_back操作替代赋值运算符,参数是容器本身。
注意:使用插入迭代器可能导致容器中的其他对象移动位置,因此现有的迭代器变成非法,需要重新赋值(list除外,不受影响)。

int  arr[]  =   {12345} ;
vector
< int >  vi;
copy(arr, arr 
+   5 ; front_iterator(vi));
// 最终结果按序是5 4 3 2 1,因为每次调用push_front将一个数据插入到vi的前面。
Vector < int > ::iterator p  =  find(vi.begin(), vi.end(),  2 );
copy(arr, arr 
+   2 , inserter(vi, p));
// 最终结果是5 4 3 1 2 2 1,因为调用insert一次性将所有数据插入到p前。


5.混合迭代器函数:
下面两个迭代器函数非常有用:
advance(iterator, int):按照指定的数目增减迭代器。第一个参数是迭代器,第二个参数是增减的数目(前向迭代器该数必须为正,双向或者随机迭代器该数可以为负)。
distance(iterator, iterator, int&):返回到达一个迭代器所需递增操作的数目。该函数是递归的,每次递归第三个参数,因此必须初始化该参数为0然后使用该函数。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值