C++STL学习(8)迭代器
2015-10-20 10:13
393 查看
注:博客内容均来自于对《C++标准库》侯捷,华中科技大学出版社一书的笔记。转载请注明出处。
所有例程在Red Hat Linux 3.2.2-5版本上编译运行,g++的版本是 g++ (GCC) 3.2.2 20030222。
我们可以将它理解成为一个指针,它指向容器中的元素,可以用它来遍历容器。迭代器是抽象的概念,任何有迭代器行为的对象都可以叫他迭代器。
注:尽可能优先选用前置式递增运算符(++iter)而不是(iter++), 前置式的性能更好。
1> 可随机存取的容器(vector, deque)
2> strings (字符串, string, wstring)
3> 一般array (指针)
example:
#include <iterator>
void advance (InputIterator& pos, Dist n)
使用实例:
#include <iterator>
Dist distance(InputIterator pos1, InputIterator pos2)
注:这里返回的型别Dist由迭代器决定:
example:
计算list<int>中两个迭代器的距离,则Dist返回的类型就是:
list<int>::difference_type
使用实例:
#include <algorithm>
void iter_swap(ForwardIterator pos1, ForwardIterator pos2)
注:迭代器的型别可以不同,但是所指的两个值必须能相互赋值!
使用实例:
注:rbegin()和rend()分别传回容器中的最后一个位置和第一个元素前的位置。
上述三种安插型迭代器分别举例子说明:
print.h
#ifndef __PRINT_H
#define __PRINT_H
#include <iostream>
template <class T>
inline void PRINT_ELEMENTS (const T& col1, const char* optcstr="")
{
typename T::const_iterator pos;
std::cout << optcstr;
for(pos = col1.begin(); pos != col1.end(); ++pos)
{
std::cout << *pos << ' ';
}
std::cout << std::endl;
}
#endifmain.cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include "print.h"
using namespace std;
int main()
{
vector<int> col1;
//为col1创建一个后置配接器 --方式1
back_insert_iterator<vector<int> > iter(col1);
//使用后置配置节向col1插值
*iter = 1;
iter++;
*iter = 2;
iter++;
iter = 3;
PRINT_ELEMENTS(col1);
//直接创建后置配接器并插值 --方式2
back_inserter(col1) = 44;
back_inserter(col1) = 55;
PRINT_ELEMENTS(col1);
//reserve足够空间以便后面的数据插入
//reserve后col1中的值和迭代器均不改变
col1.reserve(2*col1.size());
PRINT_ELEMENTS(col1);
//使用后置配接器
copy(col1.begin(), col1.end(), back_inserter(col1));
PRINT_ELEMENTS(col1);
return 0;
}
#include <iostream>
#include <list>
#include <algorithm>
#include "print.h"
using namespace std;
int main()
{
list<int> col1;
//为col1创建一个前置配接器 --方式1
front_insert_iterator<list<int> > iter(col1);
//使用配接器iter给col1插值
*iter = 1;
iter++; //不移动iter也是可以的!!
*iter = 2;
iter++;
iter = 3;
PRINT_ELEMENTS(col1);
//直接使用前置配接器给col1插值 --方式2
front_inserter(col1) = 44;
front_inserter(col1) = 55;
PRINT_ELEMENTS(col1);
//直接使用前置配接器插值
copy(col1.begin(), col1.end(), front_inserter(col1));
PRINT_ELEMENTS(col1);
}
#include <iostream>
#include <set>
#include <list>
#include <algorithm>
#include "print.h"
using namespace std;
int main()
{
set<int> col1;
//创建一个普通配接器 --方式1
insert_iterator<set<int> > iter(col1, col1.begin());
//使用定义好的配接器给容器插值
*iter = 1;
iter++; //不移动iter也是可以的!!
*iter = 2;
iter++;
iter = 3;
PRINT_ELEMENTS(col1);
//直接使用配接器给容器插值 --方式2
inserter(col1, col1.end()) = 44;
inserter(col1, col1.end()) = 55;
PRINT_ELEMENTS(col1, "set:");
list<int> col2;
//使用配接器将col1中值逐次插入到col2的开始位置
copy(col1.begin(), col1.end(), inserter(col2, col2.begin()));
PRINT_ELEMENTS(col2, "list:");
//使用配接器将col1中值逐次插入到col2第一个元素后
copy(col1.begin(), col1.end(), inserter(col2, ++col2.begin()));
PRINT_ELEMENTS(col2, "list:");
}
下面举个例子来说明ostream流迭代器的使用:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
//创建一个输出流迭代器
ostream_iterator<int> intWriter(cout, "\n");
*intWriter = 42;
intWriter++; //不移动iter也是可以的!!
*intWriter = 77;
intWriter++;
*intWriter = -5;
vector<int> col1;
for(int i=1; i<=9; ++i)
{
col1.push_back(i);
}
copy(col1.begin(), col1.end(), ostream_iterator<int>(cout));
cout << endl;
copy(col1.begin(), col1.end(), ostream_iterator<int>(cout," < "));
cout<<endl;
return 0;
}
同样,举例来说明istream的使用:
#include <iostream>
#include <iterator>
using namespace std;
int main()
{
//创建一个读取int类型的输入流迭代器
istream_iterator<int> intReader(cin);
//创建一个结束流迭代器
istream_iterator<int> intReadEOF;
while(intReader != intReadEOF)
{
cout << "once: " << *intReader << endl;
cout << "once again: "<< *intReader << endl;
++intReader;
}
}
assoiter.cpp
至此,迭代器基本上就基本介绍完了。通过这些例子和迭代器的分类,得出结论:我们确实可以将它理解成为一个指针,它指向容器中的元素,可以用它来遍历容器,对容器进行操作,等等。
所有例程在Red Hat Linux 3.2.2-5版本上编译运行,g++的版本是 g++ (GCC) 3.2.2 20030222。
1、迭代器到底是什么?
根据书上定义:迭代器是一种“能够遍历某个序列内所有元素”的对象。我们可以将它理解成为一个指针,它指向容器中的元素,可以用它来遍历容器。迭代器是抽象的概念,任何有迭代器行为的对象都可以叫他迭代器。
2、迭代器分类
迭代器可以分为:1、Input迭代器
Input迭代器只能一次一个向前读取元素,按此顺序一个个传回元素值。几乎所有的迭代器都有Input迭代器的能力。Input迭代器的各项操作如下表:注:尽可能优先选用前置式递增运算符(++iter)而不是(iter++), 前置式的性能更好。
2、Output迭代器
Output迭代器和Input迭代器正好相反,其作用是将元素一个个写入。Output迭代器的各项操作如下表:3、Forward迭代器
Forward迭代器是Inputd迭代器和Output迭代器的结合,具有Input迭代器的全部功能和Output迭代器的大部分功能。其功能如下表所示:4、Random迭代器
支持Random迭代器的型别如下:1> 可随机存取的容器(vector, deque)
2> strings (字符串, string, wstring)
3> 一般array (指针)
example:
#include <iostream> #include <string> #include <vector> #include <deque> #include <algorithm> using namespace std; void print(int elem) { cout << elem << ' '; } int main() { vector<int> col1; for(int i=0; i<9; ++i) { col1.push_back(i); } cout << "the source elements in the vector" << endl; for_each(col1.begin(), col1.end(), print); cout << endl << endl; vector<int>::iterator pos; cout << "iterator output:" << endl; for(pos = col1.begin(); pos!= col1.end(); ++pos) { cout << *pos << ' '; } cout << endl << endl; cout << "the reference output" << endl; for(int i=0; i<9; ++i) { cout << col1.begin()[i] << ' '; } cout << endl << endl; return 0; }运行结果:
3、迭代器相关辅助函数
1> advance() 迭代器前进(双向迭代器支持后退操作)
函数原型:#include <iterator>
void advance (InputIterator& pos, Dist n)
使用实例:
#include <iostream> #include <string> #include <iterator> #include <algorithm> using namespace std; int main() { istream_iterator<string> cinPos(cin); ostream_iterator<string> coutPos(cout, " "); while(cinPos != istream_iterator<string>()) { advance(cinPos, 2); if(cinPos != istream_iterator<string>()) { *coutPos++ = *cinPos++; } } cout<<endl; return 0; }
2> distance() 计算迭代器之间的距离
函数原型:#include <iterator>
Dist distance(InputIterator pos1, InputIterator pos2)
注:这里返回的型别Dist由迭代器决定:
example:
计算list<int>中两个迭代器的距离,则Dist返回的类型就是:
list<int>::difference_type
使用实例:
#include <iostream> #include <list> #include <algorithm> using namespace std; int main() { list<int> col1; for(int i=0; i<9; ++i) { col1.push_back(i); } list<int>::iterator pos; pos = find(col1.begin(), col1.end(), 5); if(pos != col1.end()) { list<int>::difference_type dis = distance(col1.begin(), pos); cout << "difference between beginning and 5: " << dis << endl; } else { cout << "5 not found! " << endl; } return 0; }
3> iter_swap() 交换两个迭代器所指的内容
函数原型:#include <algorithm>
void iter_swap(ForwardIterator pos1, ForwardIterator pos2)
注:迭代器的型别可以不同,但是所指的两个值必须能相互赋值!
使用实例:
#include <iostream> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { list<int> col1; for(int i=1; i<=9; ++i) { col1.push_back(i); } copy(col1.begin(), col1.end(), ostream_iterator<int>(cout, " ")); cout << endl; iter_swap(col1.begin(), ++col1.begin()); copy(col1.begin(), col1.end(), ostream_iterator<int>(cout, " ")); cout<<endl; iter_swap(col1.begin(), --col1.end()); copy(col1.begin(), col1.end(), ostream_iterator<int>(cout, " ")); cout<<endl; return 0; }
4、迭代器配接器
1> reverse迭代器 (逆向迭代器)
reverse迭代器重新定义递增运算和递减运算,使其行为正好倒置。注:rbegin()和rend()分别传回容器中的最后一个位置和第一个元素前的位置。
2> insert迭代器(安插型迭代器)
insert迭代器用来向容器中安插元素。back insert, front insert, general insert 都属于insert迭代器。insert迭代器的种类入下表:上述三种安插型迭代器分别举例子说明:
A.back insert 例子
首先,来看back inserter的例子,这里使用vector容器,因为vector容器是支持push_back()操作的。这里只要选用支持push_back()操作的容器都是可以实现的。头文件print.h前面已经使用过的,为了方便查看,再次贴上。print.h
#ifndef __PRINT_H
#define __PRINT_H
#include <iostream>
template <class T>
inline void PRINT_ELEMENTS (const T& col1, const char* optcstr="")
{
typename T::const_iterator pos;
std::cout << optcstr;
for(pos = col1.begin(); pos != col1.end(); ++pos)
{
std::cout << *pos << ' ';
}
std::cout << std::endl;
}
#endifmain.cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include "print.h"
using namespace std;
int main()
{
vector<int> col1;
//为col1创建一个后置配接器 --方式1
back_insert_iterator<vector<int> > iter(col1);
//使用后置配置节向col1插值
*iter = 1;
iter++;
*iter = 2;
iter++;
iter = 3;
PRINT_ELEMENTS(col1);
//直接创建后置配接器并插值 --方式2
back_inserter(col1) = 44;
back_inserter(col1) = 55;
PRINT_ELEMENTS(col1);
//reserve足够空间以便后面的数据插入
//reserve后col1中的值和迭代器均不改变
col1.reserve(2*col1.size());
PRINT_ELEMENTS(col1);
//使用后置配接器
copy(col1.begin(), col1.end(), back_inserter(col1));
PRINT_ELEMENTS(col1);
return 0;
}
B.front inerter 例子
由上表可以看到,front inserter 采用的是push_front()操作,这点要特别注意,因为vector是不支持push_front()操作的。所以这里选用list容器来实现。print.h不再贴出来浪费空间。#include <iostream>
#include <list>
#include <algorithm>
#include "print.h"
using namespace std;
int main()
{
list<int> col1;
//为col1创建一个前置配接器 --方式1
front_insert_iterator<list<int> > iter(col1);
//使用配接器iter给col1插值
*iter = 1;
iter++; //不移动iter也是可以的!!
*iter = 2;
iter++;
iter = 3;
PRINT_ELEMENTS(col1);
//直接使用前置配接器给col1插值 --方式2
front_inserter(col1) = 44;
front_inserter(col1) = 55;
PRINT_ELEMENTS(col1);
//直接使用前置配接器插值
copy(col1.begin(), col1.end(), front_inserter(col1));
PRINT_ELEMENTS(col1);
}
C.普通inerter 例子
普通inserter的例子其实已经使用过,也随处可见。不过为了对比理解,贴上一例无妨。#include <iostream>
#include <set>
#include <list>
#include <algorithm>
#include "print.h"
using namespace std;
int main()
{
set<int> col1;
//创建一个普通配接器 --方式1
insert_iterator<set<int> > iter(col1, col1.begin());
//使用定义好的配接器给容器插值
*iter = 1;
iter++; //不移动iter也是可以的!!
*iter = 2;
iter++;
iter = 3;
PRINT_ELEMENTS(col1);
//直接使用配接器给容器插值 --方式2
inserter(col1, col1.end()) = 44;
inserter(col1, col1.end()) = 55;
PRINT_ELEMENTS(col1, "set:");
list<int> col2;
//使用配接器将col1中值逐次插入到col2的开始位置
copy(col1.begin(), col1.end(), inserter(col2, col2.begin()));
PRINT_ELEMENTS(col2, "list:");
//使用配接器将col1中值逐次插入到col2第一个元素后
copy(col1.begin(), col1.end(), inserter(col2, ++col2.begin()));
PRINT_ELEMENTS(col2, "list:");
}
3> 流迭代器
A. ostream流迭代器
下面举个例子来说明ostream流迭代器的使用:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
//创建一个输出流迭代器
ostream_iterator<int> intWriter(cout, "\n");
*intWriter = 42;
intWriter++; //不移动iter也是可以的!!
*intWriter = 77;
intWriter++;
*intWriter = -5;
vector<int> col1;
for(int i=1; i<=9; ++i)
{
col1.push_back(i);
}
copy(col1.begin(), col1.end(), ostream_iterator<int>(cout));
cout << endl;
copy(col1.begin(), col1.end(), ostream_iterator<int>(cout," < "));
cout<<endl;
return 0;
}
B. istream流迭代器
同样,举例来说明istream的使用:
#include <iostream>
#include <iterator>
using namespace std;
int main()
{
//创建一个读取int类型的输入流迭代器
istream_iterator<int> intReader(cin);
//创建一个结束流迭代器
istream_iterator<int> intReadEOF;
while(intReader != intReadEOF)
{
cout << "once: " << *intReader << endl;
cout << "once again: "<< *intReader << endl;
++intReader;
}
}
5、实现一个迭代器
assoiter.h#ifndef __ASSOITER_H #define __ASSOITER_H #include <iterator> //继承自std::iterator<std::output_iterator_tag, void, void, void, void> //Container:容器型别 eg: set<int> template<class Container> class asso_insert_iterator : public std::iterator <std::output_iterator_tag, void, void, void, void> { protected: Container& container; public: explicit asso_insert_iterator (Container& c) : container(c) { } asso_insert_iterator<Container>& operator= (const typename Container::value_type& value) { container.insert(value); return *this; } asso_insert_iterator<Container>& operator* () { return *this; } asso_insert_iterator<Container>& operator++ () { return *this; } asso_insert_iterator<Container>& operator++ (int) { return *this; } }; template <class Container> inline asso_insert_iterator<Container> asso_inserter (Container& c) { return asso_insert_iterator<Container>(c); } #endif
assoiter.cpp
#include <iostream> #include <set> #include <algorithm> #include "print.h" #include "assoiter.h" using namespace std; int main() { set<int> col1; asso_insert_iterator<set<int> > iter(col1); *iter = 1; iter++; *iter = 2; iter++; iter = 3; PRINT_ELEMENTS(col1); asso_inserter(col1) = 44; asso_inserter(col1) = 55; PRINT_ELEMENTS(col1); int vals[] = {33, 67, -4, 13, 5, 2}; copy(vals, vals+5, asso_inserter(col1)); PRINT_ELEMENTS(col1); return 0; }
至此,迭代器基本上就基本介绍完了。通过这些例子和迭代器的分类,得出结论:我们确实可以将它理解成为一个指针,它指向容器中的元素,可以用它来遍历容器,对容器进行操作,等等。
相关文章推荐
- 浅谈C语言中的强符号、弱符号、强引用和弱引用
- Leetcode Sort Colors
- C++ 枚举类型(enum)
- C++语言里静态变量和全局变量
- DCM医学影像文件的格式与读取方法分享
- 重温C语言 总结指针遗忘点
- C++ STL :stack & queue 常用操作
- HTML:C语言打印excel表格并在HTML上点击保存
- HTML:C语言打印excel表格并在HTML上点击保存
- (一)黑马程序员——c语言之 switch 和 if 的使用比较
- Leetcode NO.266 Palindrome Permutation
- Leetcode NO.293 Flip Game
- C++变量初始化问题
- C++中的字面值指定类型
- Find Median from Data Stream leetcode 295
- C语言学习—函数指针
- C语言面试题整理(来自百度文库)
- C++中虚函数表的介绍
- Win7用VC++6.0出现MFCO42D.DLL丢失
- poco c++框架:本质概述