This part focuses on some aspects of the usage of common iterators, and analyzes the relationships and conversions between iterator, const_iterator, reverse_iterator, and const_reverse_iterator in STL. The content is relatively small and simple.
Item26: prefer iterator to const iterator, reverse_iterator, and const_reverse_iterator.
First, let's look at the relationship between the four iterators:
Some of them can be obtained through implicit conversion, while others can be obtained through the base () member function. The input parameters in insert and erase of the vector method are of the iterator type. The main reasons for replacing other iterators with iterator are as follows: 1. Some versions of insert and erase require iterator. 2. const_iterator cannot be implicitly converted to iterator. Handwriting conversion is not universal and inefficient. 3. The iterator converted from reverse_iterator may need to be adjusted after the conversion. The Comparison Between iterator and const_iterator may cause some trouble. Consider the following code:
typedef deque<int> IntDeque;typedef IntDeque::iterator Iter;typedef IntDeque::const_iterator ConstIter;Iter i;ConstIter ci;...if (i == ci) ...
In the comparison process, iterator is implicitly converted to const_iterator. If some implementations set the = Operator of const_iterator to a member function rather than a non-member function, this code cannot pass, A simple solution is to swap I and CI positions. When performing arithmetic operations between const and non-const random access iterators, you must use static_case to forcibly convert iterator to const_iterator.
Item 27. use distance and advance to convert a container's const_iterators to iterators. generally, const_iterator is converted to iterator by static_cast in other ways, while reverse_iterator and const_reverse_iterator are classes, and cannot be forcibly converted. The conversion between them can be implemented using distance and advance, as shown in the following code:
typedef deque<int> IntDeque;typedef IntDeque::iterator Iter;typedef IntDeque::const_iterator ConstIter;IntDeque d;ConstIter ci;...Iter i(d.begin());advance(i, distance(i, ci));
The above code has a problem. The distance parameter is two inputiterator type iterators, and I and CI are two different types of iterators. The solution is to explicitly declare parameters:
advance(i, distance<ConstIter>(i, ci));
The appeal conversion efficiency may be linear time, depending on the distance time, which varies with different types of iterator.
Item 28. Understand how to use a reverse_iterator's base iterator. reverse_iterator the corresponding iterator can be obtained through base (). The specific relationship is as follows:
To delete the element indicated by RT, we can convert it to iterator and then delete it, as shown below:
vector<int> v;...vecot<int>::reverse_iterator ri = find(v.rbegin(), v.rend(), 3);v.erase(--ri.base());
However, for vector and string, some implemented iterator adopts the built-in pointer. C/C ++ requires that the pointer returned by the function cannot be directly modified, so we can adjust reverst_iterator to avoid modifying the base () returned value:
v.erase((++ri).base());
Item 29. Consider istreambuf_iterators for character-by-Character Input. Consider copying a text file to a string:
ifstream inputFile("interestingData.txt");string fileData((istream_iterator<char>(inputFile)),istream_iterator<char>());
In this method, space in the file cannot be copied to the string. istream_iterator uses the> operator to read the space. spaces are ignored by default. One way is to clear the skipws flag:
inputFile.unset(ios::skipws);
However, the efficiency of this method is not very high. Operator> is to format the input. Each call requires a lot of operations, such as creating and destroying the sentry object, checking the stream flag (skipws, etc.), and checking the error, exception Handling. STL provides an efficient tool: istreambuf_iterators. For example, the istream_iterator <char> object uses operator> to read a single character from the input stream. The istreambuf_iterator <char> object enters the stream buffer and directly reads the next character, which can be changed as follows:
ifstream inputFile("interestingData.txt");string fileData((istreambuf_iterator<char>(inputFile)),istreambuf_iterator<char>());
Istreambuf_iterator does not ignore any characters and does not need to change the skipws flag. You can use ostreambuf_iterator for output without formatting characters.