精华内容
下载资源
问答
  • C++迭代器

    2017-06-14 17:07:16
    C++迭代器

    所有标准库容器都支持迭代器,只有少数几种支持下标运算符如string和vector。迭代器有有效和无效之分,和指针差不多,有效的迭代器或者指向某个元素或者指向容器中尾元素的下一位置,其他所有情况都是无效。

    使用迭代器

    获取迭代器不是使用取地址符,有迭代器的类型同时拥有返回迭代器的成员,如:

    vector<int> v = {1, 2, 3};
    auto a = v.begin(), e = v.end();

    begin成员返回指向容器的第一个元素的迭代器,而end成员返回指向容器“尾元素的下一个位置”的迭代器,即为一个容器本不存在的尾后元素,没有什么实际含义仅是一个标记,表示已经处理完容器中的所有元素。end成员返回的迭代器常被称作尾后迭代器(off-the-end iterator)或者尾迭代器(end iterator)。特殊情况下如果容器为空,则begin和end返回的是同一个迭代器。

    迭代器运算符

    有如下一些运算(部分):

    *iter                       //返回迭代器所指元素的引用,iter必须合法并确实指向某个元素
    iter->mem                   //解引用iter并取得该元素名为mem的成员,等价于(*iter).mem
    ++iter                      //令iter指向容器中的下一个元素
    --iter                      //令iter指向容器中的前一个元素
    iter1 == iter2              //判断两个迭代器是否相等,即是否指向同一个元素
    iter1 != iter2

    可以使用++或者–将迭代器从一个元素移到另一个元素。
    因为end返回的迭代器并不实际指向某个元素,所以不可以对其进行递增或者解引用操作。
    所有标准库容器的迭代器都定义了==和!=,但是它们中的大多数都没有定义<运算符。

    迭代器类型

    拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代器类型:

    vector<int>::iterator it;
    string::iterator it2;
    
    vector<int>::const_iterator it3;
    string::const_iterator it4;

    const_iterator和指向常量的指针差不多,能读取但不能修改它所指的元素值。如果vector对象或者string对象是一个常量,只能使用const_iterator,如果不是常量,则const_iterator和iterator都可以。

    begin和end运算符

    begin和end运算符返回的具体类型由对象是否是常量来决定的,如果对象是常量。begin和end返回const_iterator,如果对象不是常量,则返回iterator。
    C++11新标准引入了两个新函数,分别是cbegin和cend,类似于begin和end,只不过不论对象是否是常量,返回值都是const_iterator。

    解引用和成员访问操作

    解引用迭代器可获得迭代器所指的对象,如果该对象类型恰好是类,则可能可以访问它的成员。如:

    (*it).empty();

    其表达式含义是,先对it解引用,然后对解引用的结果再执行点运算符,必须加括号,如果不加,则点运算符由it来执行,而非it解引用的结果。

    (*it).empty();          //正确
    *it.empty();            //错误

    C++定义了箭头运算符(->)把解引用和成员访问两个操作结合起来,即it->mem与(*it).mem含义相同。

    某些对vector对象的操作回使迭代器失效

    任何一种可能改变vector对象容量的操作比如push_back,都会使该vector对象的迭代器失效。但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素。

    迭代器运算

    string和vector的迭代器提供了更多额外的运算符,如:

    iter + n                //迭代器加上一个整数值仍是一个迭代器,新位置与原来相比向前移动了n个元素,结果迭代器或者指示容器内一个元素,或者指示容器尾元素的下一个位置
    iter - n                //迭代器减去一个整数值仍是一个迭代器,新位置与原来相比向后移动了n个元素,结果迭代器或者指示容器内一个元素,或者指示容器尾元素的下一个位置
    iter1 += n              //迭代器加法的复合赋值语句
    iter1 -= n              //迭代器剪发的复合赋值语句
    iter1 - iter2           //结果是它们之间的距离,即将运算符右侧的迭代器向前移动差值个元素后将得到左侧的迭代器,参与运算的两个迭代器必须指向的是同一个容器中的元素或者尾元素的下一个位置
    >, >=, <, <=            //迭代器的关系运算符,如果某迭代器指向的容器位置在另一个迭代器所指的位置之前,则说前者小于后者,参与运算的两个迭代器必须指向的是同一个容器中的元素或者尾元素的下一个位置

    只要两个迭代器指向的是同一容器中的元素或者尾元素的下一个位置,就能将其相减,所得结果是两个迭代器的距离,其类型是名为difference_type的带符号整数,string和vector都定义了difference_type,因为这个距离可正可负,所以difference_type是带符号类型的。

    展开全文
  • c++迭代器

    2021-04-01 22:24:53
    c++迭代器 定义 迭代器是一种检查容器内元素并遍历元素的数据类型。 标准库为每一种标准容器(包括 vector)定义了一种迭代器类型。迭代器 类型提供了比下标操作更通用化的方法:所有的标准库容器都定义了相应的迭代...

    c++迭代器

    定义

    迭代器是一种检查容器内元素并遍历元素的数据类型。
    标准库为每一种标准容器(包括 vector)定义了一种迭代器类型。迭代器
    类型提供了比下标操作更通用化的方法:所有的标准库容器都定义了相应的迭代
    器类型,而只有少数的容器支持下标操作。因为迭代器对所有的容器都适用,现
    代 C++ 程序更倾向于使用迭代器而不是下标操作访问容器元素,即使对支持下
    标操作的 vector 类型也是这样。
    例如:
    vector::iterator it1;
    vector::iterator it2;

    begin操作

    迭代器的bigin()函数返回迭代器的第一个元素。

    end操作

    迭代器的end()函数返回迭代器“末端元素的下一个”。表明它指向了一个不存在的元素。

    迭代器的自增和解引用运算

    迭代器类型可使用解引用操作符(dereference operator)(*)来访问迭
    代器所指向的元素:
    *iter = 0;

    迭代器比较

    可以用 == 或者 != 操作符来比较两个迭代器,如果两个迭代器指向同一个元素,则相等,否则不等。

    迭代器使用示例

    vector<string> vectorStr(4, "hello");
    vector<string>::iterator itstr;
    for (itstr = vectorStr.begin(); itstr != vectorStr.end(); ++itstr)
     {
         cout << *itstr <<" ";
     }
     cout << endl;
    

    迭代器的算术操作

    iter + n //表示迭代器向前偏移N个元素。
    iter - n //表示迭代器向后偏移N个元素。
    iter1 - iter2 //表示两个迭代器之间的距离。

    例如:可以通过下面的方法获取某个vector中的中间元素
    vector::iterator mid = vi.begin() + vi.size() / 2;

    ps 注意:

    任何改变 vector 长度的操作都会使已存在的迭代器失效。例
    如,在调用 push_back 之后,就不能再信赖指向 vector 的迭
    代器的值了。

    参考《c++ primer 第四版》

    展开全文
  • C++ 迭代器

    2018-09-13 18:50:00
    Reference: 一步一步的理解C++迭代器
    展开全文
  • C++迭代器 C++迭代器 C++迭代器 C++迭代器 C++迭代器
  • c++ 迭代器

    2016-02-16 16:34:08
    迭代器是一个纯粹的抽象概念:...C++标准程序库提供了数个预先定义的特殊迭代器,亦即所谓迭代器配接器(iterator adapters)。它们不仅起辅助作用,还能赋予整个迭代器抽象概念更强大的能力。  1、Insert itera

    转自:点击打开链接

    迭代器是一个纯粹的抽象概念:任何东西,只要其行为类似迭代器,它就是一个迭代器。因此,你可以撰写一些类别(classes),具备迭代器接口,但有着各不相同的行为。C++标准程序库提供了数个预先定义的特殊迭代器,亦即所谓迭代器配接器(iterator adapters)。它们不仅起辅助作用,还能赋予整个迭代器抽象概念更强大的能力。
         1、Insert iterators (安插型迭代器)
         2、Stream iterators (流迭代器)
         3、Reverse iterators (逆向迭代器)


    Stream iterators

    Stream迭代器是一种迭代器配接器,通过它,你可以把stream当成算法的原点和终点。更明确的说,一个istream迭代器可以用来从input stream中读元素,而一个ostream迭代器可以用来对output stream写入元素。Stream迭代器的一种特殊形式是所谓的stream缓冲区迭代器,用来对stream缓冲区进行直接读取和写入操作。

    Ostream迭代器可以被赋予的值写入output stream中。下表列出ostream迭代器的各项操作。

    算式

    效果

    ostream_iterator<T>(ostream)

    ostream产生一个ostream迭代器

    ostream_iterator<T>(ostream, delim)

    ostream产生一个ostream迭代器,各元素间以delim为分隔符(请注意,delim的型别是const char*

    *iter

    无实际操作(传回iter

    iter = value

    value写到ostream,像这样:ostream<<value。其后再输出一个delim(分隔符;如有定义的话)

    ++iter

    无实际操作(传回iter

    iter++

    无实际操作(传回iter


    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<iterator>
    
    using namespace std;
    
    int main()
    {
    	
    	ostream_iterator<int> intWriter(cout, "\n");
    	*intWriter = 43;
    	intWriter++;//无实际操作
    	*intWriter = 77;
    	intWriter = -5;
    
    	vector<int> coll;
    	for (int i = 1; i <= 9; ++i)
    	{
    		coll.push_back(i);
    	}
    	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    	cout << endl;
    	system("pause");
    }
    


    输出:

    43
    77
    -5
    1 2 3 4 5 6 7 8 9



    istream迭代器是ostream迭代器的拍档,用来从input stream读取元素。透过istream迭代器,算法可以从stream中直接读取数据。istream迭代器的各项操作。产生一个istream迭代器时,必须提供一个input stream作为参数,迭代器从中读取数据。然后它便经由input迭代器的一般接口,利用operator<<读取数据。然而,读取动作有可能失败(可能到达文件尾部,或读取错误),此外算法也要知道区间是否到达终点。为解决这些问题,可以使用一个end_of_stream迭代器,可以利用默认构造函数生成。只要有任何一次读取失败,所有istream迭代器都会变成end_of_stream迭代器,所以进行一次读取后, 应该将istream迭代器和end_of_stream迭代器比较一番。

    算式

    效果

    istream_iterator<T>()

    产生一个end-of-stream迭代器

    istream_iterator<T>(istream)

    istream产生的一个迭代器(可能立即去读第一个元素)

    *iter

    传回先前读取的值(如果构造函数并未立刻读取第一个元素值,则本式执行读取任务)

    iter->member

    传回先前读取的元素的成员(如果有的话)

    ++iter

    读取下一个元素,并传回其位置

    iter++

    读取下一个元素,并传回迭代器指向前一个元素

    iter1 == iter2

    检查iter1iter2是否相等

    iter1 != iter2

    检查iter1iter2是否不相等

    注意:istream迭代器的构造函数会打开stream,读取第一个元素。所以,不要过早定义它。如果满足一下条件我们说两个istream迭代器相等:

    两者都是end_of_stream迭代器

    两者都可以再进行读取操作(未变为end_of_stream迭代器),并指向相同的stream。


    #include<iostream>
    #include<iterator>
    
    using namespace std;
    
    int main()
    {
    	
    	istream_iterator<int> intReader(cin);
    	istream_iterator<int> intReaderEOF;
    	while (intReader != intReaderEOF)
    	{
    		cout << "once:" << *intReader << endl;
    		cout << "once again:" << *intReader << endl;
    		++intReader;
    	}
    
    	system("pause");
    }
    


    输出:字符f导致程序结束。

    1 2 3 f 4
    once:1
    once again:1
    once:2
    once again:2
    once:3
    once again:3


    Stream迭代器的另一个例子:

    #include<iostream>
    #include<iterator>
    #include<string>
    #include<algorithm>
    
    using namespace std;
    
    int main()
    {
    	
    	istream_iterator<string> cinPos(cin);
    	ostream_iterator<string> coutPos(cout, " ");
    	istream_iterator<string> intReaderEOF;
    	while (cinPos != intReaderEOF)
    	{
    		advance(cinPos, 2);
    		if (cinPos != intReaderEOF)//跳过两个位置后是否到达end_of_stream
    		{
    			*coutPos++= *cinPos++;
    		}
    	}
    	cout << endl;
    	system("pause");
    }
    


    输入:

    No one objects if you are doing a good programming job for someone who you respe
    ct.

    输出:
    objects are good for you


    Reverse Iterators

    逆向迭代器重新定义递增运算和递减运算,使其行为正好倒置。

    deque<int>::iterator pos1,pos2;//coll元素:1,2,3,4……9
    pos1=find(coll.begin(),coll.end(),2);
    pos2=find(coll.begin(),coll.end(),7);
    for_each(pos1,pos2,print);     //输出:2 3 4 5 6
    
    deque<int>::reverse_iterator rpos1(pos1);
    deque<int>::reverse_iterator rpos2(pos2);
    for_each(rpos2,rpos1,print);    //输出:6 5 4 3 2
    


    迭代器pos1和pos2定义了一个半开区间,包括2不包括7。当把描述这一区间的两个迭代器转换为Reverse迭代器时,该区间仍然有效,而且可以被逆序处理。

    将迭代器转换为逆向迭代器:container::reverse_iterator(it);//it为迭代器

    将逆向迭代器转换回来:rpos.base();//rpos为逆向迭代器


    Insert iterators

    Insert迭代器,也称为inserters,用来将“赋值新值”操作转换为“安插新值”操作。通过这种迭代器,算法可以执行安插(insert)行为而非覆盖(overwrite)行为。所有Insert迭代器都隶属于Output迭代器类型,所以它只提供赋值(assign)新值的能力。通常算法会将数值赋值给目的迭代器,如copy()算法

    namespace std{
    template<class Inputiterator,class Outiterator,Outputiterator>
    Outputiterator copy(Inputiterator from_pos,Inputiterator from_end,Outputiterator to_pos)
    {
       while(from_pos!=from_end)
       {
          *to_pos=*from_pos;
          ++from_pos;
          ++to_pos;
       }
    }
    }

    *to_pos=*from_pos;

    insert迭代器可以把上述这样的赋值转化为安插操作。不过实际上里面有两个操作:首先operator*传回迭代器当前位置(为何不是值,看下面表),然后再由operator=赋值新值,即安插操作。注意:

    1、operator*被视作一个无实际动作的动作(no-op),简单返回一个*this,对于insert迭代器来说,*pos与pos等价。

    2、赋值动作被转化为安插操作,事实上insert迭代器会调用push_back(),push_front()或insert()成员函数。

    下表列出Insert迭代器的所有操作函数。

    表达式

    效果

    *iter

    无实际操作(传回iter

    iter = value

    安插value

    ++iter

    无实际操作(传回iter

    iter++

    无实际操作(传回iter

    C++标准程序库提供三种Insert迭代器:back inserters, front inserters, general inserters。它们的区别在于插入位置。事实上它们各自调用所属容器中不同的成员函数。所以Insert迭代器初始化时要清楚知道自己所属的容器是哪一种。每一种insert迭代器都可以由一个对应的便捷函数加以生成和初始化。下表列出不同的insert迭代器及其能力。

    名称

    Class

    其所调用的函数

    便捷函数

    Back inserter

    back_inserter_iterator

    push_back(value)

    back_inserter(cont)

    Front inserter

    front_insert_iterator

    push_front(value)

    front_inserter(cont)

    General inserter

    insert_iterator

    insert(pos, value)

    inserter(cont, pos)

    back inserters(安插于容器最尾端),内部调用push_back(),在容器尾端插入元素。只有支持push_back()的vector、deque、list、string可以使用Back inserters。

    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<iterator>
    
    using namespace std;
    
    int main()
    {
    	vector<int> coll;
    	back_insert_iterator<vector<int>> iter(coll);
    
    	iter = 1;
    	*iter = 2;//等价iter=1
    	++iter;//无实际操作
    	iter++;//无实际操作
    	iter = 3;
    	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    	cout << endl;
    
    	back_inserter(coll) = 44;
    	back_inserter(coll) = 45;
    	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    	cout << endl;
    
    	coll.reserve(2 * coll.size());
    	copy(coll.begin(), coll.end(), back_inserter(coll));
    	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    	cout << endl;
    
    	system("pause");
    }
    


    注意,一定要在调用copy()之前确保有足够大的空间,因为back inserter在安插元素时,可能会造成指向该vector的其它迭代器失效。

    输出:

    1 2 3
    1 2 3 44 45
    1 2 3 44 45 1 2 3 44 45


    Front inserters(安插于容器最前端),内部调用push_front(),在容器前端插入元素。只有支持push_front()的deque、list可以使用Front inserters。

    #include<iostream>
    #include<list>
    #include<algorithm>
    #include<iterator>
    
    using namespace std;
    
    int main()
    {
    	list<int> coll;
    	front_insert_iterator<list<int>> iter(coll);
    
    	iter = 1;
    	*iter = 2;//等价iter=1
    	++iter;//无实际操作
    	iter++;//无实际操作
    	iter = 3;
    	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    	cout << endl;
    
    	front_inserter(coll) = 44;
    	front_inserter(coll) = 45;
    	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    	cout << endl;
    
    	copy(coll.begin(), coll.end(), front_inserter(coll));
    	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    	cout << endl;
    
    	system("pause");
    }
    


    输出:

    3 2 1
    45 44 3 2 1
    1 2 3 44 45 45 44 3 2 1


    General inserters(一般性安插器),内部调用insert(),将元素插入到pos所指位置的前方。所有STL容器都提供insert()成员函数,所以这是唯一可用于关联式容器的预定义inserter。根据两个参数初始化:容器和待安插位置。安插操作完成后,General inserters获得刚刚被安插的那个元素的位置,实际上相当于以下语句:

    pos=container.insert(pos,value);
    ++pos;


    然后新获得的位置再下次安插时使用。

    #include<iostream>
    #include<set>
    #include<list>
    #include<algorithm>
    #include<iterator>
    
    using namespace std;
    
    int main()
    {
    	set<int> coll;
    	insert_iterator<set<int>> iter(coll,coll.begin());
    
    	iter = 1;
    	*iter = 2;//等价iter=1
    	++iter;//无实际操作
    	iter++;//无实际操作
    	iter = 3;
    	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    	cout << endl;
    
    	inserter(coll, coll.begin()) = 44;
    	inserter(coll, coll.begin()) = 45;
    	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    	cout << endl;
    
    	list<int> coll2;
    	copy(coll.begin(), coll.end(), inserter(coll2,coll2.begin()));
    	copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));
    	cout << endl;
    
    	copy(coll.begin(), coll.end(), inserter(coll2, ++coll2.begin()));
    	copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));
    	cout << endl;
    	system("pause");
    }
    

    输出:

    1 2 3
    1 2 3 44 45
    1 2 3 44 45
    1 1 2 3 44 45 2 3 44 45

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,272
精华内容 4,908
关键字:

c++迭代器

c++ 订阅