STL container iterator failure

Source: Internet
Author: User

It is well known that when an insert or erase function of a container is used to insert or delete elements through the iterator "may" cause the iterator to become invalid. Therefore, many suggestions are to let us obtain the iterator returned by the insert or erase, in order to re-obtain the new valid iterator for the correct operation:

View plaincopy to clipboardprint?
Iter = Vec. insert (ITER );
Iter = Vec. Erase (ITER );
It is not hard to understand why the iterator fails. Taking vector as an example, when we insert an element, when its pre-allocated space is not enough, it will apply for a new space and copy the elements in the original space to the new space, then, the newly added elements are placed at the end of the new space to meet the needs of continuous storage of vector elements. Then the original space will be revoked by the system or used for other purposes, so the iterator pointing to the original space becomes something similar to the "suspension Pointer" and points to an illegal area. If such an iterator is used, it will lead to serious running errors and become natural. This is also why many books have described that the insert operation of vector "may result in the effectiveness of all iterators. But here I can't help but think that the erase operation of vector is described as "it will cause the iterator pointing to the deleted element and the deleted element to become invalid ". However, it is obvious that erase is much less ineffective than insert. It seems that "This invalidation is not due to another", and it seems like this: the erase operation is performed in the original space, suppose there is a vector with a sequence of "12345" <int> the iterator that the container originally points to 3 is nothing more than 4 after I delete 2, I just need to pay attention not to use the iterator that exceeds the end position?

After talking about this, it seems that the type of the iterator failure can be summarized:

1. Because of the overall "Migration" of container elements, the space for storing the original container elements is no longer valid, and the iterator pointing to the original space becomes invalid.

2. The deletion of elements changes the order of some elements, so that the iterator originally pointing to an element no longer points to the element you want to point.

There is no good reason for the first type. For the second type, I wrote the followingCode

View plaincopy to clipboardprint?
Vector <int> VEC;
For (INT I = 0; I <10; I ++)
VEC. push_back (I );
 
Vector <int>: iterator iter = Vec. Begin () + 2;
VEC. Erase (ITER); // Note: it is not recommended to write this statement here.
Cout <* ITER <Endl;
For (vector <int >:: iterator it = VEC. Begin (); it! = Vec. End (); It ++)
Cout <* It <Endl;

According to my guess, although my comment is "dangerous", I did not discuss the first category of failure type.ProgramAs expected, we should still Delete 2 at the VEC [2] location, then output 3 at the VEC [2] location, and output all numbers ranging from 0 to 10 without 2, therefore, running in the C ++ environment of vs2008 turned out to be a heartless "Red Cross ". It is reasonable to say that this writing method is definitely not prone to serious runtime errors. Is it wrong to guess?

At that time, I was troubled by such questions for a few days. One day I suddenly remembered an example about container iterator parameters. It couldn't be run in vs2008, but it could be done in vc6.0, some people say that 08 adopts a more rigorous type detection mechanism. So I put the above Code in 6.0, which really achieved the expected results. It seems that the system did this. As for why 08 is not available, I can only think that a more secure inspection mechanism is adopted. The consequence of the failure of the second type is also "Unforgivable ".

In this way, I thought that if the original space is sufficient when the insert element is used, wouldn't the first type become invalid and the second type become invalid?

View plaincopy to clipboardprint?
vector VEC;
for (INT I = 0; I <10; I ++)
Vec. push_back (I);
cout <"Capacity:" vector : iterator iter = Vec. begin () + 2;
Vec. insert (ITER, 100);
cout <"Capacity:" cout <* ITER for (vector : iterator it = Vec. begin (); it! = Vec. end (); It ++)
cout <* It It also proves that the hypothesis is correct under vc6.0. However, the above practices only help me understand the causes of the effectiveness of the iterator. We recommend that you use insert and erase operations as described in many books, such as the first code, this is a good and safe habit. In a word, I believe that "All iterators will become invalid after the insert and erase operations ".

Iterator is an object that can perform pointer-like operations on it (for example, removing the reference (operator * () and increasing (operator ++, we can understand it as a pointer. But it is not a common pointer. We can call it a generalized pointer. You can view it through sizeof (vector: iterator), and the memory occupied is not 4 bytes.

First, for vector, adding and deleting operations may invalidate some or all of the iterators of the container. Why does the iterator fail? Vector elements are stored sequentially in the memory. Imagine: if there are already 10 elements in the current container, we need to add another element to the container, however, there is no free space behind the 10 elements in the memory, and the elements of the vector must be stored sequentially while accessing the index. Therefore, we cannot find a place in the memory to store this element. Therefore, the vector must re-allocate the bucket to store the original elements and newly added elements: the elements stored in the old bucket are copied to the new bucket, and new elements are inserted, finally, cancel the old bucket. In this case, all iterators of the vector container will become invalid.

We can see that the above-mentioned method of allocating and revoking memory space achieves the self-growth of vector, and the efficiency is extremely low. To enable the vector container to implement fast memory allocation, the actually allocated container will have more space than the space currently required. The vector container reserves these additional storage areas to store newly added elements, instead of allocating a new bucket each time. You can see this mechanism from the implementation of capacity and reserve in vector.

Difference between capacity and size: size indicates the number of elements currently owned by the container, while capacity indicates the total number of elements that the container can store before it has to allocate a new bucket.

Several cases of invalidation of the vector iterator: 1. When an element is inserted (push_back), The iterator returned by the end operation will certainly become invalid. 2. When an element is inserted (push_back), the return value of capacity is different from that before the element is inserted. Then, the entire container needs to be reloaded, And the iterator returned by the first and end operations will become invalid. 3. After the delete operation (erase, pop_back) is performed, all the iterators pointing to the delete vertex are invalid. All the iterators pointing to the elements behind the delete vertex are also invalid.

Deque iterator invalidation: This is the limitation in C ++ Primer: 1. inserting elements in the first or end of the deque container will not invalidate any iterator. 2. Deleting an element at its header or tail will only invalidate the iterator pointing to the deleted element. 3. The insert and delete operations at any other location of the deque container will invalidate all iterators pointing to the container element. However, I found in vs2005 that the first one was not satisfied. Why? Wait for the STL to go deep and then understand it slowly!

Only list iterators seem to be ineffective in rare cases. Maybe when you delete the node, the iterator pointing to the deleted node will become invalid. Nothing else has been found.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.