C + + iterator invalidation

Source: Internet
Author: User
Tags lua

1. First from one to the topic start depicting the iterator expires. Sometimes we use the following method to remove vector elements naturally and confidently:

#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <string>

voidDel_elem (vector<string> &vec,Const Char*elem) {Vector<string>::iterator Itor =Vec.begin (); for(; Itor! = Vec.end (); itor++) { if(*itor = =elem) {vec.erase (itor); }}}template<classInputiterator>voidShow_vec (inputiterator First, Inputiterator last) { while(First! =Last ) {Std::cout<< *first <<" "; First++; } std::cout<<" "<<Std::endl;}intMain (void){ stringArr[] = {"PHP","C #","Java","JS","Lua"}; Vector<string> Vec (arr, arr+ (sizeof (arr)/sizeof (arr[0]))); Std::cout<<"before del:"<<Std::endl; Show_vec (Vec.begin (), Vec.end ()); Del_elem (VEC,"PHP"); Std::cout<<"After del:"<<Std::endl; Show_vec (Vec.begin (), Vec.end ()); return 0;}

When string arr[] = {"PHP", "C #", "Java", "JS", "Lua"}; , run the top program to get the following output:

    

The result of the operation is correct AH. Find "PHP", then delete, leaving four elements.

But in fact the Del_elem process is not the same as we imagined, in the Del_elem to print the value of each step itor, you will find clues.

Add Del_elem to log:

  

voidDel_elem (vector<string> &vec,Const Char*elem) {Std::cout<<"----------------------------"<<Std::endl; Vector<string>::iterator Itor =Vec.begin ();  for(; Itor! = Vec.end (); itor++) {Std::cout<< *itor <<Std::endl; if(*itor = =elem)        {vec.erase (itor); }} std::cout<<"----------------------------"<<Std::endl;}

Before we do the delete operation, we print the value of each element and continue compiling to run the following result:

    

When doing the Del_elem operation, less print a "C #", that is, after printing "PHP", and then delete PHP, the next print is not "C #", and directly printed "java."

Then we can comment out the vec.erase (itor), then we can get Del_elem will print all the element values,

So it appears that C # was "Gone" since the erase operation was performed.

To figure this out, let's look at the definition of a set of vector operations:

iterator Erase (iterator position) {    if1 ! = End ()        )1, Finish , position);     --finish;    Destroy (finish);     return position;}

Iterator begin () {return start;}

Iterator End () {return finish;}

We often use Vec.begin (), Vec.end (), presumably to know what start and finish are.

First look at the Erase function: first determine whether the iterator to be removed is the previous element of finish, the last element in the vector,

If it is not the last element, move all the elements behind the iterator that you want to delete forward one slot, and then--finish to reposition the finish pointer.

At this point the finish pointer points to the last element address before deletion, in this case the address of LUA, but the current value at the finish pointer is useless, so call destroy.

If the pending iterator is the previous element of finish, move the finish pointer directly and call destroy to destroy the element object at that location.

At the same time, we see that the erase function passed in the iterator, only played a position to determine the role of the erase itself does not have any action on the iterator, the value of the iterator address is still valid, but because of the copy operation, the value at position has become "C #."

And look back at our Del_elem function:

After removing the first element of PHP, before executing itor++, all elements after PHP moved forward with a slot causing the element itor to be stored in C # at this time.

Then continue to execute itor++, at this time Itor and back move, itor in the value is already java,c# that is missing out.

1-2 from this, another conclusion can be reached, when ARR has n (n>=2) consecutive PHP elements, we use the Del_elem function can not delete all the PHP elements, so this will cause a bug.

We will string arr[] = {"PHP", "C #", "Java", "JS", "Lua"}; Change to string arr[] = {"PHP", "PHP", "PHP", "PHP", "C #", "Java", "JS", "Lua"}; After that, observe the results of the operation:

    

As expected, PHP has not been removed cleanly, because when the first PHP removed, with the current Del_elem method, will always miss the deleted PHP elements, if this element happens to be "PHP", there will be a bug.

1-3 Deleting an element with the current Del_elem causes the finish to move forward to a slot, and if you put PHP in the last slot, which is the slot before finish, when you delete the last PHP, finish points to the address of the deleted PHP (which is already illegal).

Then the PHP place will be destroyed, and then execute the itor++, then the itor point to the back of the finish, when the judgment itor! = Vec.end (), the formula is set up, and then continue to execute, but when the iterator is dereferenced, it will eventually be illegal

Referring to the address, the program collapsed. Let's see if this is the case, change the last element to "PHP"; String arr[] = {"PHP", "PHP", "PHP", "PHP", "C #", "Java", "JS", "PHP"};

Compiled and run with the following results:

    

GDB debugging, found because *itor caused the program to crash.

2 The above example points out some problems caused by improper method of selecting vectors when removing elements;

1 is the deletion of multiple identical elements, because the vector itself caused the deletion of the net, a bug

2 is the last element when the element is deleted, which can cause the program to crash.

3 We know a lot of times that vector iterators fail, but most of the time we don't know what's causing the problem.

The above example enumerates the results of an iterator failure, and in turn, we'll look at the question of what a vector delete element would cause an iterator to fail.

My conclusion is that when you delete an element from a vector, before deleting the element, suppose we define some iterators that point to each other,

The position of the 1 iterator is before the iterator to be deleted.

2 iterators to be removed

3 The position of the iterator is after the iterator to be removed

Then, when erase (Itor) is called on the removed iterator, the iterator that was previously defined before Itor is still useful, and the previously defined itor and the iterator after itor have been invalidated, and the invalidation here means that the element content referred to by these iterators is not the same as the one before the deletion. It may even point to an illegal address.

This can cause bugs in the program or crash directly when working with these failed iterators.

4. How do I remove the vector element?

can refer to:

voidDel_elem (vector<string> &vec,Const Char*elem) {Vector<string>::iterator Itor =Vec.begin ();  for(; Itor! =vec.end ();) {Std::cout<< *itor <<" "<< & (*itor) <<Std::endl; if(*itor = =elem) {Itor=vec.erase (itor); personally feel that this assignment is superfluous, because erase itself does not have any action on itor, erase before and after the operation of the itor point of the position is constant, the change is only the value inside .        If you understand the error, also hope to point out in time } Else{itor++; }    }}

5. If the reader has some understanding of the iterator invalidation caused by the vector delete element, it would be easier to understand the failure of the iterator caused by the insertion element.

1 if the insert operation causes a space reconfiguration (to request a new space, to assign the value of the old space to a new space, to free up the old space), all iterators declared before the insert operation are invalidated

2 If no spatial configuration is caused, the iterator after the insertion position is invalidated.

6. If we declare some iterators, after inserting or deleting vectors, be aware that these iterators may have been invalidated.

7. The iterator of the vector fails, which can lead to the failure of the iterator of the other sequence container, and the iterator of the other associative container fails. Too much content, this article is just to give some understanding of the vector iterator failure, follow-up continue to supplement others.

<effective stl> Nineth, a more detailed discussion of the various methods of operation of the container, interested readers can self-browsing.

The level is limited, error inevitably, hope timely point out. We hope to provide some ideas for understanding the failure of iterators.

  

  

  

C + + iterator invalidation

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.