Iterator failure problem in vactor

What is iterator invalidation

The bottom layer of the iterator is actually a pointer, or the pointer is encapsulated

vectorThe iterator is a pointer T*.
An iterator points to a certain space. At this time, the space is released, and the iterator still points to the original space. This is called the failure of the iterator.

If you continue to use an expired iterator, the program may crash

insert image description here


Operations that cause iterators to become invalid

Operations that cause changes in the underlying space are likely to cause iterator failure

Iterator failure is mainly caused by insertanderase



Let's look at a insertsituation that causes iterators to fail.

We first define an vector<int>object and an iterator

void test6()
{
    
    
	vector<int> v{
    
     1,2,3,4,5,6 };
	auto it = v.begin();
}

At this time, the value of v size()and capacity()the value of are both 6. If you insert data into v, you need to expand the capacity.

void test6()
{
    
    
	vector<int> v{
    
     1,2,3,4,5,6 };
	auto it = v.begin();

	v.insert(it, 0);//此处会扩容
}

v.insert(it, 0)It will lead to expansion. Expansion actually means opening up a larger space and destroying the original space. Therefore, the iterator has expired at this time. itBecause it will not be used again it, no error will be reported for the time being.
insert image description here

insert image description here


If you use an expired iterator here again it, an error will be reported.

void test6()
{
    
    
	vector<int> v{
    
     1,2,3,4,5,6 };
	auto it = v.begin();

	v.insert(it, 0);//此处会扩容

	v.insert(it, 0);
}

insert image description here
So if you want the iterator to not expire, you need to reassign the value to the iterator.

insertThe function is defined in the library as:

iterator insert (iterator position, const value_type& val)

You can see that its return value is iteratorof type, which actually returns an iterator that does not expire after processing, and is an iterator pointing to the first newly inserted element.

void test6()
{
    
    
	vector<int> v{
    
     1,2,3,4,5,6 };
	auto it = v.begin();

	it = v.insert(it, 0);//此处会扩容
	v.insert(it, 10);//不会报错
}




Let’s take a look at erasethe circumstances that led to the failure:

In fact, in most cases, the use of eraseiterators does not result in

void test7()
{
    
    
	vector<int> v{
    
     1,2,3,4,5,6 };
	auto it = v.begin()+3;
	v.erase(it);
}

The iterator here itpoints to 4. v.erase(it)After deleting 4, the following elements will be added forward, without causing changes to the underlying space. Theoretically, the iterator should not be invalid.
insert image description here

If pos happens to be the last element, and pos happens to be the position of end after deletion, and there is no element at the end position, then pos will be invalid.
insert image description here

And, if there is only one element in the vector and the iterator happens to point to this element, then erasethe iteration will fail.

It can be seen that although erase will cause the iterator to fail in some cases, and in some cases it will not cause the iterator to fail, but in the VS environment, it is considered that when an element at any position in the vector is deleted, vs will consider the iterator at that position to be invalid. .



In fact, similar to vector, after string insertion + expansion operation + erase, the iterator will also become invalid.




Attitudes towards iterator failure in VS and g++ environments

  • In the VS environment, iterator invalidation is very strict. As long as there is an iterator invalid, the compiler will report an error; as long as an element at any position in the vector is deleted, the iterator at that position will be considered invalid and an error will be reported.
  • However, the g++ compiler on Linux is not very strict in detecting iterator failures, and the processing is not as extreme as vs.
    • After the expansion, the iterator has become invalid. Although the program can be run, the running results are no longer correct.
    • After erase deletes the code at any location, the program will still run if the iterator does not expire under Linux.
    • If the iterator deleted by erase is the last element, it has exceeded end after deletion. If ++it is used, an error will still be reported.
    • Therefore, after the iterator fails, the code will not necessarily crash, but the running result will definitely be wrong. If it is not within the range of begin and end, it will definitely crash.

Guess you like

Origin blog.csdn.net/weixin_64116522/article/details/132395901