C++标准模板库 迭代器 iterator 详解(一)

来源:互联网 发布:用王家卫 知乎 编辑:程序博客网 时间:2024/05/21 06:54

#include <vector>#include <iostream>#include <list>#include <algorithm>#include <iterator> //copyusing namespace std;template <class T>inline void print (const T& coll, const char* optcstr=""){    typename T::const_iterator pos;    std::cout << optcstr;    for (pos=coll.begin(); pos!=coll.end(); ++pos)    {        std::cout << *pos << ' ';    }    std::cout << std::endl;}void  test_random_access_iterator(){   vector<int> coll;    // insert elements from 1991 to 2013   for (int i=1991; i<=2013; ++i)   {       coll.push_back (i);   }   /* print number of elements by processing the distance between beginning and end    * - NOTE: uses operator - for iterators    */   cout << "number/distance: " << coll.end()-coll.begin() << endl;   /* print all elements    * - NOTE: uses operator < instead of operator !=    */   vector<int>::iterator pos;   for (pos=coll.begin(); pos<coll.end(); ++pos)   {       cout << *pos << ' ';   }   cout << endl;   /* print all elements    * - NOTE: uses operator [] instead of operator *    */   for (int i=0; i<coll.size(); ++i)   {       //cout << coll.begin()[i] << ' '; 和如下语句效果相同       cout << coll[i] << ' ';   }   cout << endl;   /* print every second element    * - NOTE: uses operator +=    */   for (pos = coll.begin(); pos < coll.end()-1; pos += 2)   {       cout << *pos << ' ';   }   cout << endl;}/********************************************运行结果:number/distance: 231991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 20062007 2008 2009 2010 2011 2012 20131991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 20062007 2008 2009 2010 2011 2012 20131991 1993 1995 1997 1999 2001 2003 2005 2007 2009 2011*********************************************/void test_advance(){    list<int> coll;    // insert elements from 1 to 9    for (int i=2007; i<=2014; ++i)    {        coll.push_back(i);    }    //打印整个链表    print(coll,"print the list as follow:\n");    list<int>::iterator pos = coll.begin();    // print actual element    cout<<endl;    cout << *pos << endl;    // step three elements forward    cout<<endl<<"after advance (pos, 3)\n";    advance (pos, 3);    // print actual element    cout << *pos << endl;    // step one element backward    cout<<endl<<"after advance (pos, -1)\n";    advance (pos, -1);    // print actual element    cout << *pos << endl;}/********************************************运行结果:print the list as follow:2007 2008 2009 2010 2011 2012 2013 20142007after advance (pos, 3)2010after advance (pos, -1)2009*********************************************/void test_distance(){    list<int> coll;    // insert elements from -3 to 9    for (int i=2007; i<=2014; ++i)    {        coll.push_back(i);    }    print(coll,"print the list as follow:\n");    // search element with value 2010    list<int>::iterator pos;    pos = find (coll.begin(), coll.end(),    // range                2010);                          // value    if (pos != coll.end())    {        // process and print difference from the beginning        cout << "difference between beginning and 2010: "             << distance(coll.begin(),pos) << endl;    }    else    {        cout << "2010 not found" << endl;    }}/********************************************运行结果:print the list as follow:2007 2008 2009 2010 2011 2012 2013 2014difference between beginning and 2010: 3*********************************************/void test_iter_swap(){    list<int> coll;    // insert elements from 1 to 9    for (int i=2007; i<=2014; ++i)    {        coll.push_back(i);    }    print(coll,"print list as follow:\n");    // swap first and second value    iter_swap (coll.begin(), ++coll.begin());    print(coll,"after iter_swap (coll.begin(), ++coll.begin()) \n");    // swap first and last value    iter_swap (coll.begin(), --coll.end());    print(coll,"after iter_swap (coll.begin(), --coll.end()) \n");}/********************************************运行结果:print list as follow:2007 2008 2009 2010 2011 2012 2013 2014after iter_swap (coll.begin(), ++coll.begin())2008 2007 2009 2010 2011 2012 2013 2014after iter_swap (coll.begin(), --coll.end())2014 2007 2009 2010 2011 2012 2013 2008*********************************************/void print_element (int elem){    cout << elem << ' ';}void test_reverse_iterator(){    list<int> coll;    // insert elements from 1937 to 1945    for (int i=1937; i<=1945; ++i)    {        coll.push_back(i);    }    cout<<"print all elements in normal order:\n";    for_each (coll.begin(), coll.end(),      // range              print_element);                        // operation    cout << endl;    cout<<"print all elements in reverse order:\n";    for_each (coll.rbegin(), coll.rend(),    // range              print_element);                        // operations    cout << endl;    // find position of element with value 1938    list<int>::iterator pos1;    cout<<"find [1938,1942):\n";    pos1 = find (coll.begin(), coll.end(),    // range                 1938);                          // value    cout<<"pos1 is :"<<*pos1<<endl;    list<int>::reverse_iterator rpos1(pos1);    cout<<"rpos1 is :"<<*rpos1<<endl;    cout<<"rpos1.base() is "<<*rpos1.base()<<endl;    // find position of element with value 1942    list<int>::iterator pos2;    pos2 = find (coll.begin(), coll.end(),    // range                 1942);                          // value    cout<<"pos2 is :"<<*pos2<<endl;    list<int>::reverse_iterator rpos2(pos2);    cout<<"rpos2 is :"<<*rpos2<<endl;    cout<<"rpos2.base() is "<<*rpos2.base()<<endl;    // print all elements in range [pos1,pos2)    for_each (pos1, pos2,     // range              print_element);         // operation    cout << endl;    cout<<"reverse [1938,1942):\n";    // print all elements in range [pos1,pos2) in reverse order    for_each (rpos2, rpos1,   // range              print_element);         // operation    cout << endl;}/********************************************运行结果:print all elements in normal order:1937 1938 1939 1940 1941 1942 1943 1944 1945print all elements in reverse order:1945 1944 1943 1942 1941 1940 1939 1938 1937find [1938,1942):pos1 is :1938rpos1 is :1937rpos1.base() is 1938pos2 is :1942rpos2 is :1941rpos2.base() is 19421938 1939 1940 1941reverse [1938,1942):1941 1940 1939 1938*********************************************/int main(){    return 0;}



<iterator>

Iterator definitions
An iterator is any object that, pointing to some element in a range of elements (such as an array or a container), has the ability to iterate through the elements of that range using a set of operators (with at least the increment (++) and dereference (*) operators).

The most obvious form of iterator is a pointer: A pointer can point to elements in an array, and can iterate through them using the increment operator (++). But other kinds of iterators are possible. For example, each container type (such as alist) has a specific iterator type designed to iterate through its elements.

Notice that while a pointer is a form of iterator, not all iterators have the same functionality of pointers; Depending on the properties supported by iterators, they are classified into five different categories:

Iterator categories

Iterators are classified into five categories depending on the functionality they implement:

  • InputOutput
  • Forward
  • Bidirectional
  • Random Access


Input and output iterators are the most limited types of iterators: they can perform sequential single-pass input or output operations.


Forward iterators have all the functionality of input iterators and if they are not constant iterators- also the functionality of output iterators, although they are limited to one direction in which to iterate through a range (forward). All standard containers support at least forward iterator types.

Bidirectional iterators are like forward iterators but can also be iterated through backwards.

Random-access iterators implement all the functionality of bidirectional iterators, and also have the ability to access ranges non-sequentially: distant elements can be accessed directly by applying an offset value to an iterator without iterating through all the elements in between. These iterators have a similar functionality to standard pointers (pointers are iterators of this category).

The properties of each iterator category are:

categorypropertiesvalid expressionsall categoriescopy-constructible, copy-assignable and destructibleX b(a);
b = a;
Can be incremented++a
a++
Random AccessBidirectionalForwardInputSupports equality/inequality comparisonsa == b
a != b
Can be dereferenced as an rvalue*a
a->m
OutputCan be dereferenced as an lvalue 
(only for mutable iterator types)
*a = t
*a++ = t

default-constructibleX a;
X()
Multi-pass: neither dereferencing nor incrementing affects dereferenceability{ b=a; *a++; *b; }
Can be decremented--a
a--
*a--

Supports arithmetic operators + and -a + n
n + a
a - n
a - b
Supports inequality comparisons (<, >, <= and >=) between iteratorsa < b
a > b
a <= b
a >= b
Supports compound assignment operations += and -=a += n
a -= n
Supports offset dereference operator ([])a[n]
Where X is an iterator type, a and b are objects of this iterator type, t is an object of the type pointed by the iterator type, and n is an integer value.


Functions

Iterator operations:

Iterator generators:

Classes


Predefined iterators



#include <vector>#include <iostream>#include <list>#include <algorithm>#include <iterator> //copyusing namespace std;template <class T>inline void print (const T& coll, const char* optcstr=""){    typename T::const_iterator pos;    std::cout << optcstr;    for (pos=coll.begin(); pos!=coll.end(); ++pos)    {        std::cout << *pos << ' ';    }    std::cout << std::endl;}void  test_random_access_iterator(){   vector<int> coll;    // insert elements from 1991 to 2013   for (int i=1991; i<=2013; ++i)   {       coll.push_back (i);   }   /* print number of elements by processing the distance between beginning and end    * - NOTE: uses operator - for iterators    */   cout << "number/distance: " << coll.end()-coll.begin() << endl;   /* print all elements    * - NOTE: uses operator < instead of operator !=    */   vector<int>::iterator pos;   for (pos=coll.begin(); pos<coll.end(); ++pos)   {       cout << *pos << ' ';   }   cout << endl;   /* print all elements    * - NOTE: uses operator [] instead of operator *    */   for (int i=0; i<coll.size(); ++i)   {       //cout << coll.begin()[i] << ' '; 和如下语句效果相同       cout << coll[i] << ' ';   }   cout << endl;   /* print every second element    * - NOTE: uses operator +=    */   for (pos = coll.begin(); pos < coll.end()-1; pos += 2)   {       cout << *pos << ' ';   }   cout << endl;}/********************************************运行结果:number/distance: 231991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 20062007 2008 2009 2010 2011 2012 20131991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 20062007 2008 2009 2010 2011 2012 20131991 1993 1995 1997 1999 2001 2003 2005 2007 2009 2011*********************************************/void test_advance(){    list<int> coll;    // insert elements from 1 to 9    for (int i=2007; i<=2014; ++i)    {        coll.push_back(i);    }    //打印整个链表    print(coll,"print the list as follow:\n");    list<int>::iterator pos = coll.begin();    // print actual element    cout<<endl;    cout << *pos << endl;    // step three elements forward    cout<<endl<<"after advance (pos, 3)\n";    advance (pos, 3);    // print actual element    cout << *pos << endl;    // step one element backward    cout<<endl<<"after advance (pos, -1)\n";    advance (pos, -1);    // print actual element    cout << *pos << endl;}/********************************************运行结果:print the list as follow:2007 2008 2009 2010 2011 2012 2013 20142007after advance (pos, 3)2010after advance (pos, -1)2009*********************************************/void test_distance(){    list<int> coll;    // insert elements from -3 to 9    for (int i=2007; i<=2014; ++i)    {        coll.push_back(i);    }    print(coll,"print the list as follow:\n");    // search element with value 2010    list<int>::iterator pos;    pos = find (coll.begin(), coll.end(),    // range                2010);                          // value    if (pos != coll.end())    {        // process and print difference from the beginning        cout << "difference between beginning and 2010: "             << distance(coll.begin(),pos) << endl;    }    else    {        cout << "2010 not found" << endl;    }}/********************************************运行结果:print the list as follow:2007 2008 2009 2010 2011 2012 2013 2014difference between beginning and 2010: 3*********************************************/void test_iter_swap(){    list<int> coll;    // insert elements from 1 to 9    for (int i=2007; i<=2014; ++i)    {        coll.push_back(i);    }    print(coll,"print list as follow:\n");    // swap first and second value    iter_swap (coll.begin(), ++coll.begin());    print(coll,"after iter_swap (coll.begin(), ++coll.begin()) \n");    // swap first and last value    iter_swap (coll.begin(), --coll.end());    print(coll,"after iter_swap (coll.begin(), --coll.end()) \n");}/********************************************运行结果:print list as follow:2007 2008 2009 2010 2011 2012 2013 2014after iter_swap (coll.begin(), ++coll.begin())2008 2007 2009 2010 2011 2012 2013 2014after iter_swap (coll.begin(), --coll.end())2014 2007 2009 2010 2011 2012 2013 2008*********************************************/void print_element (int elem){    cout << elem << ' ';}void test_reverse_iterator(){    list<int> coll;    // insert elements from 1937 to 1945    for (int i=1937; i<=1945; ++i)    {        coll.push_back(i);    }    cout<<"print all elements in normal order:\n";    for_each (coll.begin(), coll.end(),      // range              print_element);                        // operation    cout << endl;    cout<<"print all elements in reverse order:\n";    for_each (coll.rbegin(), coll.rend(),    // range              print_element);                        // operations    cout << endl;    // find position of element with value 1938    list<int>::iterator pos1;    cout<<"find [1938,1942):\n";    pos1 = find (coll.begin(), coll.end(),    // range                 1938);                          // value    cout<<"pos1 is :"<<*pos1<<endl;    list<int>::reverse_iterator rpos1(pos1);    cout<<"rpos1 is :"<<*rpos1<<endl;    cout<<"rpos1.base() is "<<*rpos1.base()<<endl;    // find position of element with value 1942    list<int>::iterator pos2;    pos2 = find (coll.begin(), coll.end(),    // range                 1942);                          // value    cout<<"pos2 is :"<<*pos2<<endl;    list<int>::reverse_iterator rpos2(pos2);    cout<<"rpos2 is :"<<*rpos2<<endl;    cout<<"rpos2.base() is "<<*rpos2.base()<<endl;    // print all elements in range [pos1,pos2)    for_each (pos1, pos2,     // range              print_element);         // operation    cout << endl;    cout<<"reverse [1938,1942):\n";    // print all elements in range [pos1,pos2) in reverse order    for_each (rpos2, rpos1,   // range              print_element);         // operation    cout << endl;}/********************************************运行结果:print all elements in normal order:1937 1938 1939 1940 1941 1942 1943 1944 1945print all elements in reverse order:1945 1944 1943 1942 1941 1940 1939 1938 1937find [1938,1942):pos1 is :1938rpos1 is :1937rpos1.base() is 1938pos2 is :1942rpos2 is :1941rpos2.base() is 19421938 1939 1940 1941reverse [1938,1942):1941 1940 1939 1938*********************************************/int main(){    return 0;}

std::advance

template <class InputIterator, class Distance>  void advance (InputIterator& it, Distance n);
Advance iterator
Advances the iterator it by n element positions.

If it is a random-access iterator, the function uses just once operator+ or operator-. Otherwise, the function uses repeatedly the increase or decrease operator (operator++ or operator--) until n elements have been advanced.

Parameters

it
Iterator to be advanced.
InputIterator shall be at least an input iterator.
n
Number of element positions to advance.
This shall only be negative for random-access and bidirectional iterators.
Distance shall be a numerical type able to represent distances between iterators of this type.

Return value

none


std::distance

template<class InputIterator>  typename iterator_traits<InputIterator>::difference_type    distance (InputIterator first, InputIterator last);
Return distance between iterators
Calculates the number of elements between first and last.

If it is a random-access iterator, the function uses operator- to calculate this. Otherwise, the function uses the increase operator (operator++) repeatedly.

Parameters

first
Iterator pointing to the initial element.
last
Iterator pointing to the final element. This must be reachable from first.
InputIterator shall be at least an input iterator.

Return value

The number of elements between first and last.


Summary

The Good
  • The STL provides iterators as a convenient abstraction for accessing many different types of containers.
  • Iterators for templated classes are generated inside the class scope with the syntax
    class_name<parameters>::iterator
  • Iterators can be thought of as limited pointers (or, in the case of random access iterators, as nearly equivalent to pointers)
The Gotchas
  • Iterators do not provide bounds checking; it is possible to overstep the bounds of a container, resulting in segmentation faults
  • Different containers support different iterators, so it is not always possible to change the underlying container type without making changes to your code
  • Iterators can be invalidated if the underlying container (the container being iterated over) is changed significantly

原创粉丝点击