码迷,mamicode.com
首页 > 编程语言 > 详细

C++ Primer 学习笔记_42_STL实践与分析(16)–再谈迭代器【上】

时间:2016-05-07 11:12:07      阅读:341      评论:0      收藏:0      [点我收藏+]

标签:

STL实践与分析

--再谈迭代器【上】

引言:

另外三种迭代器类型:

    1插入迭代器:这类迭代器与容器绑定在一起,实现在容器中插入元素的功能。

    2iostream迭代器:这类迭代器可以与输入与输出流绑定在一起,用于迭代遍历所关联的IO流。

    3反向迭代器:这类迭代器实现向后遍历,而不是向前遍历,所有的容器都定义了自己的reverse_iterator类型,由rbeginrend成员函数返回。

上述迭代器都在iterator头文件中定义。

一、插入迭代器

    前面曾经提到的back_inserter函数是一种插入器,插入器适宜用迭代器适配器,其带有一个容器参数,并生成一个迭代器,用于在指定容器中插入元素。通过插入迭代器赋值时,迭代器将会插入一个新的元素。

C++提供了三种插入迭代器,其差别在于插入元素的位置不同:

   1)back_inserter:创建使用push_back实现插入的迭代器。

   2)front_inserter使用push_front实现插入

   3)inserter:使用insert实现插入操作。出了所关联的容器外,inserter还带有第二个实参:指向插入起始位置的迭代器

1front_inserter需要使用push_front

    front_inserter的操作类似于back_inserter:该函数创建一个迭代器,调用它所关联的基础容器的push_front成员函数代替赋值操作。

    deque<int> iDeq;
    front_inserter(iDeq) = 1;   //OK

    vector<int> iVec;
    front_inserter(iVec) = 1;   //Error
    back_inserter(iVec) = 1;    //OK

    只有当容器提供 push_front操作,才能使用front_inserter。在vector或其他没有push_front运算的容器上使用front_inserter,将产生错误。

2inserter将产生在指定位置实现插入的迭代器

     inserter适配器提供更普通的插入形式。这种适配器带有两个实参:所关联的容器和指示起始插入位置的迭代器

    list<int>::iterator it = find(iList.begin(),iList.end(),42);
    /*
    *在创建 inserter 时,应指明新元素在何处插入。
    *inserter 函数总是在它的迭代器实参所标明的位置前面插入新元素。
    */
    replace_copy(iVec.begin(),iVec.end(),inserter(iList,it),0,100);

3inserter+容器的begin组合与 front_inserter的区别:

    在使用front_inserter,元素始终在容器的第一个元素前面插入。而使用inserter,元素则在指定位置前面插入。

    //理解下面输出的区别
    list<int> ilst,ilst1,ilst2;

    for (list<int>::size_type index = 0; index != 4; ++index)
    {
        ilst.push_front(index);
    }

    copy(ilst.begin(),ilst.end(),front_inserter(ilst1));
    copy(ilst.begin(),ilst.end(),inserter(ilst2,ilst2.begin()));

    cout << "iList1: " << endl;
    for (list<int>::iterator iter = ilst1.begin(); iter != ilst1.end(); ++iter)
    {
        cout << *iter << '\t';
    }
    cout << endl << "iList2: " << endl;
    for (list<int>::iterator iter = ilst2.begin(); iter != ilst2.end(); ++iter)
    {
        cout << *iter << '\t';
    }
    cout << endl;

【小心地雷:】

    front_inserter的使用将导致元素以相反的次序出现在目标对象中!

//P349 习题11.14
void printList(const list<int> &iList)
{
    for (list<int>::const_iterator iter = iList.begin();iter != iList.end(); ++iter)
    {
        cout << *iter << '\t';
    }
    cout << endl;
}

int main()
{
    list<int> iList;
    list<int> iList1,iList2,iList3;

    for (list<int>::size_type i = 0;i != 10; ++i)
    {
        iList.push_back(i);
    }
    cout << "iList: " << endl;
    printList(iList);

    replace_copy(iList.begin(),iList.end(),front_inserter(iList1),0,100);
    cout << "iList1: " << endl;
    printList(iList1);

    replace_copy(iList.begin(),iList.end(),inserter(iList2,iList2.begin()),0,100);
    cout << "iList2:" << endl;
    printList(iList2);

    replace_copy(iList.begin(),iList.end(),back_inserter(iList3),0,100);
    cout << "iList3:" << endl;
    printList(iList3);
}

二、iostream迭代器

      虽然iostream类型不是容器,但是标准库同样提供了iostream对象上使用的迭代器:istream_iterator用于读取输入流,而ostream_iterator用于写输出流。这些迭代器将它们所对应的流视为特定类型的元素序列。使用流迭代器时,可以用泛型算法从流对象中读取数据或写数据到流对象中。

iostream迭代器的构造函数

istream_iterator<T>in(strm);

创建从输入流strm读取T类型对象istream_iterator对象

istream_iterator<T>in;

istream_iterator对象的超出末端迭代器

ostream_iterator<T>in(strm);

创建T类型的对象写入到输出流strmostream_iterator对象

ostream_iterator<T>in(strm,delim);

创建将T类型的对象写入到输出流strmostream_iterator对象,再写入过程中使用delim作为元素的分隔符。delimit是以空字符结束的字符数组。

     流迭代器只定义了最基本的迭代器操作:自增、解引用和赋值。此外,可比较两个istream迭代器是否相等(或不等)ostream迭代器则不提供比较运算

istream_iterator的操作

it1== it2

it1!= it2

比较两个istream_iterator对象是否相等/不等。迭代器必须读取的是相同的类型。如果两个迭代器都是end值,则它们相等。对于两个都不指向流结束符位置的迭代器,如果它们使用同一个输入流构造,则它们也相等

*it

返回从流中读取的值

it-> mem

(*it).mem的同义词,返回从流中读取的对象的mem成员

++it

it++

通过使用元素类型提供>>操作符从输入流中获取下一个元素值,使迭代器向前移动。通常,前缀版本使迭代器再流中向前移动,并返回对加1后的迭代器的引用。而后缀版本使迭代器在流中向前移动后,返回原值

1、流迭代器的定义

    流迭代器都是类模板:任何已定义输入操作符(>>操作符)的类型都可以定义stream_iterator。类似地,任何已定义输出操作符(<<操作符)的类型也可定义ostream_iterator

    在创建流迭代器时,必须指定迭代器所读写的对象类型:

    istream_iterator<int> cin_it(cin);
    istream_iterator<int> end_of_stream;

    ofstream outfile;
    ostream_iterator<Sales_item> cout_it(outfile," ");

【注意:】

    ostream_iterator对象必须与特定的流绑定在一起。在创建istream_iterator,可直接将它绑定到一个流上。另一种方法是在创建时不提供实参,则该迭代器指向超出末端位置。ostream_iterator不提供超出末端迭代器

    在创建ostream_iterator对象时,可提供第二个(可选的)实参,指定将元素写入输出流时使用的分隔符。分隔符必须是C风格字符串。因为它是C风格字符串,所以必须以空字符结束;否则,其行为将是未定义的。

2istream_iterator对象上的操作

    构造与流绑定在一起的istream_iterator对象时,将对迭代器定位,以便第一次对该迭代器进行解引用时即可从流中读取第一个值。

    vector<int> iVec;
    istream_iterator<int> in_iter(cin);
    istream_iterator<int> eof;

    while (in_iter != eof)
    {
        iVec.push_back(*in_iter++);
    }

    while循环从cin中读取 int型数据,并将读入的内容保存在iVec中。每次循环都检查in_iter是否为 eof。其中eof迭代器定义为空的istream_iterator对象,用作结束迭代器。绑在流上的迭代器在遇到文件结束或某个错误时(如输入的是字符),将等于结束迭代器的值。

    //可以这样重写该<span class="wp_keywordlink" style="margin: 0px; padding: 0px; border: 0px; background: transparent;"><a target=_blank href="http://www.xuebuyuan.com/" title="程序" target="_blank" style="text-decoration: none; color: rgb(1, 150, 227);">程序</a></span>
    istream_iterator<int> in_iter(cin);
    istream_iterator<int> eof;

    vector<int> iVec(in_iter,eof);

这里,用一对标记元素范围的迭代器构造vector对象。这些迭代器是istream_iterator对象,这就意味着这段范围的元素是通过读取所关联的流来获得的

C++ Primer 学习笔记_42_STL实践与分析(16)–再谈迭代器【上】

标签:

原文地址:http://blog.csdn.net/selfi_xiaowen/article/details/51334750

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!