Reprint to: http://blog.csdn.net/wangshihui512/article/details/9791517
iterator invalidation: Typical iterator invalidation.
First, for vectors, the add and delete operations may invalidate some or all of the iterators in the container. Then why does the iterator fail? Vector elements are stored sequentially in memory, imagine: if 10 elements already exist in the current container, and now add an element to the container, but in memory immediately after the 10 elements there is no free space, and vector elements must be stored in order to index access, So we can't find a place to store this element anywhere in memory. The vector must then reallocate the storage space to hold the original elements and the newly added elements: the elements stored in the old storage space are copied into the new storage space, the new elements are inserted, and the old storage space is finally revoked. This happens and will cause all iterators in the vector container to fail. We see the realization of the above-mentioned allocation and revocation of memory space in order to achieve the vector's self-growth, efficiency is extremely low. In order for the vector container to achieve fast memory allocation, the actual allocation of containers will be more than the current space required, the vector container reserved These additional storage, to hold the newly added elements, and do not need to reallocate new storage space each time. You can see this mechanism by implementing capacity and reserve members from a vector. Capacity and size differences: size is the number of elements that the container currently owns, while capacity refers to the total number of elements that the container can store before it must allocate new storage space.
failure condition of vector iterator:
1. When an element is inserted (push_back), the iterator returned by the end operation is definitely invalidated.
2. When an element is inserted (push_back), the capacity return value changes before the element is inserted, and the entire container needs to be reloaded, and the iterator returned by the begin and end operations will be invalidated.
3. After the delete operation (Erase,pop_back), the iterator to the delete point is all invalidated, and the iterator to the element that follows the delete point will all be invalidated.
failure conditions for deque iterators:
1. Inserting elements in the Deque container header or tail does not invalidate any iterators.
2. Deleting an element at its first or trailing end only invalidates the iterator that points to the deleted element.
3. The insert and delete operation at any other location in the Deque container invalidates all iterators that point to the container element.
failure conditions for List/set/map iterators:
When deleted, iterators that point to the deleted node are invalidated
List<int> intlist;
List<int>::iterator it = Intlist.begin ();
while (It! = Intlist.end ())
{
it = intlist.erase (it);
......
}
summarize various container features (1) Vector
Internal data structure: array.
Random access to each element, the time required is constant.
The time required to add or delete elements at the end is independent of the number of elements, and the time required to add or delete elements in the middle or at the beginning varies linearly with the number of elements.
Elements can be dynamically added or reduced, memory management is done automatically, but programmers can use the reserve () member function to manage memory.
The vector's iterator is invalidated when the memory is reassigned (the element it points to is no longer the same as before or after the operation). When more than capacity ()-size () elements are inserted into the vector, memory is reassigned, all iterators are invalidated, otherwise iterators that point to any element after the current element are invalidated. When an element is deleted, an iterator that points to any element after the deleted element is invalidated.
(2) deque
Internal data structure: array.
Random access to each element, the time required is constant.
The time required to add elements at the beginning and end is independent of the number of elements, and the time required to add or delete elements in the middle varies linearly with the number of elements.
Elements can be dynamically increased or decreased, memory management is done automatically, and no member functions are provided for memory management.
Adding any element will invalidate the deque iterator. Deleting an element in the middle of a deque invalidates the iterator. When you delete an element at the head or tail of a deque, only the iterator that points to that element is invalidated.
(3) List
Internal data structure: Two-way loop linked list.
An element cannot be accessed randomly.
Bidirectional traversal is possible.
The time required to add or remove elements at the beginning, end, and anywhere in the middle is constant.
Elements can be dynamically added or reduced, and memory management is done automatically.
Adding any element does not invalidate the iterator. When you delete an element, other iterators are not invalidated except for the iterator that points to the currently deleted element.
(4) Slist
Internal data structure: one-way linked list.
Cannot traverse in two directions, only from front to back.
Other features are similar to list.
(5) Stack
Adapter, which converts any type of sequence container to a stack, typically using deque as a supported sequence container.
The element can only last in, first out (LIFO).
You cannot traverse the entire stack.
(6) Queue
Adapter, which converts any type of sequence container into a queue, typically using deque as a supported sequence container.
The element can only be first in and out (FIFO).
You cannot traverse the entire queue.
(7) Priority_queue
Adapter, which converts any type of sequence container into a priority queue, typically using vectors as the underlying storage method.
Only the first element can be accessed and the entire priority_queue cannot be traversed.
The first element is always the highest-priority element.
(8) Set
Key is unique.
The elements are sorted in ascending order by default.
If the element that the iterator points to is deleted, the iterator is invalidated. Any other operation that adds or removes an element does not invalidate the iterator.
(9) Multiset
Keys can be not unique.
Other features are the same as set.
(map)
Key is unique.
The ascending order of the element default keys.
If the element that the iterator points to is deleted, the iterator is invalidated. Any other operation that adds or removes an element does not invalidate the iterator.
(one) Multimap
Keys can be not unique.
Other features are the same as map.
1. Iterator Type of container
Each container type defines its own type of iterator, such as Vector:vector::iterator iter;
This statement defines a variable named ITER whose data type is the iterator type defined by the vector. Each standard library container type defines a member named iterator, where the iterator has the same meaning as the actual iterator type.
2. Begin and end Operations
Each container defines a pair of functions named Begin and end, which are used to return iterators. If there are elements in the container, the iterator returned by begin points to the first element: Vector::iterator iter = Ivec.begin ();
The above statement initializes ITER to the value returned by the vector operation named begin. Assuming that the vector is not empty, after initialization, ITER means that the element is ivec[0].
The iterator returned by the end operation points to the next "end element of the vector". is often referred to as an out-of-end iterator (Off-the-end iterator), indicating that it points to a non-existent element. If the vector is empty, begin returns an iterator that is the same as the iterator returned by end.
The iterator returned by the end operation does not point to any actual element in the vector, but instead it acts as a Sentinel (Sentinel), indicating that we have processed all the elements in the vector.
3. Vector iterator self-increment and dereference operation
The iterator type defines actions to get the element that the iterator points to, and allows the programmer to move the iterator from one element to another.
An iterator type can use the dereference operator (* operator) to access the R element that the iterator points to:
*iter = 0;
The dereference operator returns the element to which the iterator is currently pointing. Assuming that ITER points to the first element of the vector object Ivec, then *iter and ivec[0] are pointing to the same element. The effect of the above statement is to assign the value of this element to 0.
The iterator uses the increment operator to move the iterator forward to point to the next element in the container. Logically, the self-increment of an iterator is similar to the self-increment operation of an int object. For an int object, the result of the operation is to "add 1" to the int value, while the iterator object is to "move forward one position" in the container. Therefore, if ITER points to the first element, then ++iter points to the second element.
Because the iterator returned by the end operation does not point to any element, it cannot be dereferenced or self-increment.
4. Other operations of the iterator
Another pair of actions that can be performed on iterators is comparison: compare two iterators with the = = or! = operator, and if the two iterator objects point to the same element, they are equal, otherwise they are not equal.
5. Example of a program used by an iterator
Suppose you have declared a vector-type Ivec variable, to reset all its element values to 0, you can do this with subscript:
Reset all the elements in Ivec to 0
for (Vector::size_type IX = 0; IX! = Ivec.size (); ++ix)
Ivec[ix] = 0;
The above program iterates through the elements of the Ivec with a For loop, and the For Loop defines an index IX, which will increment by 1 for each iteration of the loop. The For loop body assigns each element of the Ivec a value of 0
Summary:
1, for the deletion of the associative container (map, list, set) element, the insert operation will invalidate the iterator that points to the element, and the other element iterators are unaffected.
2, for the deletion of the sequential container (vector) element, the insertion operation causes an iterator that points to the element and subsequent elements to be invalidated.
about Iterators
(1) Characteristics and operation
The basic features of iterators are:
Dismiss--Supports dereferencing (dereference) operations so that the values it references are accessible. That is, if P is an iterator, then *p and p-> should be defined (like pointers);
Assignment-An iterator can be assigned to another iterator. That is, if both P and Q are iterators, the expression p=q should be defined;
Comparison-an iterator can be compared to another iterator. That is, if both P and Q are iterators, the expressions p==q and p!=q should be defined;
Traversal-You can use iterators to traverse elements in a container, which can be achieved by defining ++p and p++ operations for the iterator p.
The operations of iterators are:
Read--indirectly referencing the value of an element in a container by dereferencing *, for example, x = *p;
Write-assigns a value to the element in the container by dereferencing *, for example *p = x;
Access--through subscripts and pointers to the elements in the container and their members, such as p[2] and p->m
Iterations--traversing, roaming, and jumping in containers using increment and decrement operations (+ + and--、 + and-, + = and-=), such as p++ 、--p, p+5, p-=8
Comparison--Using the comparison operator (= =,! =, <, >, <=, >=) to compare whether two iterators are equal or who are small, such as if (P < q) ..., Wihle (P! = c.end ()) ...;
(2) Classification
The following 5 types of iterators are defined in the STL, depending on the operations supported by the iterator:
Input iterators(input iterator)--used to read information in a container, but not necessarily to modify it.
Input iterator ITER reads the value of the element it points to in the container by de-referencing (that is, *iter);
In order for an input iterator to have access to the values of all the elements in the container, it must be supported by the + + operator (pre/suffix format);
The input iterator does not guarantee that the second time the container is traversed, the order is constant, and it cannot be guaranteed to increment before the previously pointed value is unchanged. That is, any algorithm based on an input iterator should be single make (Single-pass), independent of the value at the time of the previous traversal, and not dependent on the previous value in the traversal.
A visible input iterator is a one-way, read-only iterator that can increment but cannot be decremented and can be read-only and not writable. Suitable for single make read-only algorithms.
Output iterators(output iterator)--for transmitting information to a container (modifying the value of an element in a container), but not read. For example, a display is a device that can only write unreadable, and it can be represented by an output container. also supports dereferencing and + + operations, and is also single make. Therefore, the output iterator is suitable for single make write-only algorithms.
forward iterators(Forward iterator forward iterator)--you can only use the + + operator to traverse a container in one direction (not using--). As with I/O iterators, forward iterators also support dereferencing and + + operations. Unlike an I/O iterator, a forward iterator isMulti-Pass(Multi-Pass). That is, it always traverses the container in the same order, and after the iterator is incremented, the same value can still be obtained by releasing the saved iterator reference. In addition, a forward iterator can be either read-write or read-only.
bidirectional iterators(bidirectional iterator)--you can use the + + and--operators to traverse the container in both directions. Others, like forward iterators, also support dereference, multi-pass, read-write, or read-only.
Random-Access iterators(Random access iterator)-a bidirectional iterator that can directly access any element in the container.
As you can see, these 5 iterators form a hierarchy: I/O iterators (both + + traversal, but the former read/write only) the most basic, forward iterators can read and write but only + + traversal, bidirectional iterators can read and write but can ++/--bidirectional traversal, random iterators in addition to bidirectional traversal can also be random access.
(3) Pointers and iterators
Since the iterator is a generalized pointer, is the pointer itself an iterator? In fact, the pointer satisfies the requirements of all iterators, so the pointer is an iterator.
An iterator is an interface to a generic algorithm, and a pointer is an iterator. Therefore, various STL algorithms can also use pointers to operate on non-standard containers (such as arrays). That is, using pointers as iterators, you can use STL algorithms for regular arrays.
For example, sort the functions of sort:
Sort (ran first, ran last); Ran represents a random-access iterator
The container C is:
Sort (C.begin (), C.end ());
Array A can be changed to: (const int SIZE = 100; float a[size];)
Sort (A, a + SIZE);
Another example is copying a function copy:
Copy (in first, on last, out res); In and out represent input and output iterators, respectively
The container c<int> can be: (ostream_iterator<int> out_iter (cout);)
Copy (C.begin (), C.end (), out_iter);
Array A can be changed to: (const int SIZE = 100; float a[size];)
Copy (A, A + SIZE, C.begin ());
C + +: STL iterators and iterator invalidation issues