您的位置:首页 > 编程语言 > C语言/C++

《C++ Primer》读书笔记第十章-2-再探迭代器 And 泛型算法结构

2017-09-20 11:47 363 查看
笔记会持续更新,有错误的地方欢迎指正,谢谢!

再探迭代器

除了前面介绍的标准库容器迭代器外,C++还在头文件iterator中定义了额外的集中迭代器:

插入迭代器:绑定到容器上,可用来向容器中插入元素。

流(iostream)迭代器:绑定到输入输出流上,可用来遍历所关联的IO流。

反向迭代器:跟普通的迭代器方向相反(forward_list没有这个,你懂得)。

移动迭代器:是移动元素而不是拷贝元素(是不是很诱人~以后再详细介绍)。

插入迭代器

有三种:

back_inserter, inserter,front_inserter

插入迭代器:back_inserter、inserter、front_inserter分别调用容器操作push_back、insert、push_front。

vector<int> vec;
auto it = back_inserter(vec);
*it = 0; //{0},尾插
auto is = front_inserter(vec);
*is = -1; //{-1, 0},头插

list<int> lst1 = {1, 2, 3};
list<int> lst2;
copy(lis1.cbegin(), lst1.cend(), inserter(lst2, lst2.begin()) ); //lst2拷贝了lst1


流迭代器

虽然iostream不是容器,但标准库还是定义了这些类型对象的迭代器。istream_iterator读取输入流,ostream_iterator向一个输出流写数据。

流迭代器将它们对应的流当作一个特定类型的元素序列(类似容器)来处理。通过使用流迭代器,我们可以使用泛型算法从流对象读取数据以及向其写入数据

下面是一个用istream_iterator从标准输入读取数据,存入一个vector的例子:

istream_iterator<int> in_iter(cin); //从cin读取int
istream_iterator<int> eof; //空的istream_iterator当作istream尾后迭代器
while(in_iter != eof)
{
vec.push_back(*in_iter++);//先对in_iter解引用后,最后才把in_inter自增1。
}


我们来个牛逼的写法:

istream_iterator<int> in_iter(cin), eof;
vector<int> vec(in_iter, eof);


这两行代码和上面的程序完全等价:我们用一对元素范围的迭代器来构造vec,这个构造函数通过in_iter从cin中读取数据,直到遇到文件尾或者遇到不是int的数据为止,从流中读取的数据用于构造vec。

再来个酷炫的,输入数据求和:

istream_iterator<int> in(cin), eof;
cout << accumulate(in, eof, 0) << endl; //从标准输入中读取数值求和输出


补充:如果两个istream_iterator都是尾后迭代器或绑定到相同的输入则相等。

反向迭代器

来个例子,逆序打印vec中的元素:

vector<int> vec = {1, 2, 3};
for(auto r_iter = vec.crbegin(); r_iter != vec.crend(); ++r_iter)
{
cout << *r_iter << endl;
}


使用反向迭代器的时候,要注意的就是+ +和- -时的前进方向。

不懂的看下图:



泛型算法结构

都是对之前一些细节的总结,就不说了,没什么实质内容。

特定容器算法-链表list和forward_list

与其他容器不同,链表定义了独有的一些函数:sort(), merge(), remove(), reverse()和unique(),可改变底层容器,优先使用它们而不是通用算法。因为通用的sort()要求随机访问迭代器,因此不能用于链表,链表要用双向迭代器或前向迭代器。

函数说明:

函数含义
lst.merge(lst2)(重载版:lst.merge(lst, comp))将lst2的元素并入lst中,二者原先必须是有序的。第一个版本使用的是<运算符;第二个版本使用自定义比较操作。合并后,lst2变为空。
lst.remove(val)(重载版:lst.remove_if(pred))函数会调用erase()删除与val相等或使一元谓词pred为真的所有元素。
lst.reverse()翻转lst的元素顺序。
lst.sort()(重载版:lst.sort(comp))使用<或自定义比较操作排序元素。
lst.unique()(重载版:lst.unique(pred))调用erase()删除同一个值的连续拷贝。第一个版本使用==,第二个版本使用给定的二元谓词
splice成员:链表特有的算法,将一个链表的一截移动到另一个链表的指定位置,要保证移动的目的位置不在待移动范围内
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ c++primer 读书笔记