The base member function that calls reverse_iterator can generate a "corresponding" iterator. However, this sentence is a bit disappointing. For example, let's take a look at this code. First, we put the numbers 1-5 into a vector, and then generate a reverse_iterator pointing to 3.
The base of reverse_iterator initializes an iterator: Vector <int> v;
V. reserve (5); // See Clause 14
For (int I = 1; I <= 5; ++ I) {// insert 1 to 5 to the vector
V. push_back (I );
}
Vector <int>: reverse_iterator ri = // point the ri to 3
Find (v. rbegin (), v. rend (), 3 );
Vector <int>: iterator I (ri. base (); // make the base of I and ri the same
After executing the above code, you can think of the results as follows:
This figure shows the reverse_iterator and its corresponding base.
The exclusive offset between iterator is like rbegin () and rend () and related begin () and end (), but it does not say anything you need to know.
In particular, it does not explain how to implement the operations you want to perform on ri. Some container member functions only accept parameters of the iterator type, so if you want
To insert a new element at the position specified by ri, you cannot directly do this because the insert function of vector does not accept reverse_iterator. If you want to delete the ri
The elements at the specified position also have the same problem. Erase member functions reject reverse_iterator and insist on iterator. To complete deletion and some forms of insertion
You must first use the base function to convert reverse_iterator to iterator and then use iterator to complete the operation.
Let us assume that you want to insert a new element v at the position specified by ri. Specifically, we assume that the value you want to insert is 99. Remember that ri is on
The traversal order in the figure is from right to left, and the insert operation inserts new elements into the ri position, and moves the elements in the original ri position to the traversal process.
We think 3 should appear on the left side of 99. After the insert operation, v looks like this:
Of course, we cannot use ri to specify the insert location because it is not an iterator. We must use I instead. As mentioned above, when ri points to 3, I (that is, ri. base () points to 4. If we use ri to specify the insert position, we use I to point to the insert position. That assumption is correct. What is the conclusion?
● Insert a new element at the position specified by a reverse_iterator ri and insert it at the position pointed by ri. base. For
In the insert operation, ri and ri. base () are equivalent, and ri. base () are actually iterator corresponding to ri.
Now let's consider deleting elements. Review the relationship between ri and I in the initial vector (that is, before inserting 99:
If you want to delete the elements pointed to by ri, you cannot directly use I, because I and ri do not point to the same element. Therefore, you need to delete the first element of I.
● To delete an element at the position specified by a reverse_iterator ri, delete the previous element of ri. base. For delete operations, ri and ri. base () are not equivalent, and ri. base () is not the iterator corresponding to ri.
We still need to look at the delete operation code, because it is quite surprising. Vector <int> v;
// Insert 1 to 5 to v, same as above
Vecot <int >:: reverse_iterator ri =
Find (v. rbegin (), v. rend (), 3); // same as above, ri points to 3
V. erase (-- ri. base (); // try to delete the element before ri. base (); for vector, compilation fails.
This design does not have any problems. Expression -- ri. base () indicates the elements that need to be deleted. Besides
All containers other than vector and string. It may also be able to process vector and string, but for most implementations of vector and string, it does not. Here
Under the sample implementation, iterator (and const_iterator) will use the built-in pointer to implement the implementation, so the result of ri. base () is a pointer. Both C and C ++ specify
The pointer returned by the function cannot be directly modified. Therefore, on the STL platform where the string and vector iterators are pointers, expressions such as -- ri. base () cannot be compiled. To move
When you delete an element from a position specified by reverse_iterator, try to avoid modifying the return value of the base. No problem. If you cannot reduce the return values of base calls,
You only need to add the reverse_iterator value first, and then call base!
// Same as above
V. erase (++ ri). base (); // Delete the element pointed to by ri;
// No problem with this compilation!
Because this method applies to all standard containers, This is the preferred technique for deleting an element pointed out by reverse_iterator.
It is clear that the base member function of reverse_iterator returns a "corresponding" iterator statement. For the insert operation, it is true that
This is not the case for delete operations. When you need to convert reverse_iterator to iterator, it is very important that you know what you are going to do.
The returned iterator, because only in this way can you determine whether the iterator you get is what you need.