快捷搜索: 王者荣耀 脱发

STL迭代器失效的场景总结

一、序列式容器迭代器失效的场景

序列式容器以vector为例。分别有以下情况会失效:

1、push_back() 使迭代器失效。

在容器末尾添加一个元素。如果容器有剩余空间(capacity() > size()),则直接添加新元素到容器尾部。此时,原迭代器中end()会失效,其他的都不会失效。如果容器没有剩余空间(capacity() == size()),会导致容器重新分配内存,然后将数据从原内存复制到新内存,再在尾部添加新元素。此时,由于内存重新分配,原迭代器(所有)都失效。

2、pop_back() 使迭代器失效。

直接将容器中的最后一个元素删除,原迭代器中最后一个元素的迭代器和end()会失效,其余的都不会失效。

3、insert(iterator, n) 使迭代器失效。

如果容器有剩余空间,先在容器尾部插入一个元素,然后将插入点及之后的元素都向后移动一位,然后在插入点创建新元素。否则,会导致容器重新分配内存,接着将插入点之前的元素复制过去,在插入点创建新元素,再将插入点之后的元素复制过去。因此 ,如果没有内存的重新分配,原迭代器中插入点及插入点之后的迭代器(包括end())都失效。如果有内存的重新分配,原迭代器(所有)都失效。

4、erase(iterator) 使迭代器失效。

将删除点及之后的元素都向前移动一位,然后删除最后一个元素。因此,原迭代器中删除点之前的迭代器都有效,删除点之后的元素迭代器都失效。

二、关联式容器迭代器失效场景

set、multiset、map、multimap, 使用红黑树来存储数据。

1、insert(iterator) 插入不会使得任何迭代器失效;

2、删除运算使指向删除位置的迭代器失效,但是不会失效其他迭代器。erase迭代器只是被删元素的迭代器失效,返回值为被删除元素的下一个迭代器,所以要采用 iter=contan.erase(iter)和erase(iter++)的方式删除迭代器。erase(iter++)的删除方法对于内存连续的容器,例如vector不可用,因为被删除元素的下一个迭代器也失效了;iter=contan.erase(iter)则都可行。

三、防止因迭代器失效导致异常

1、删除多个元素方法:

for(vector<T>::iterator iter=veci.begin(); iter!=veci.end(); )
{
          
   
	if(判断删除的元素的条件)
	{
          
   
		{
          
   //元素类型T为原始指针时
			//T tmp = *iter;
			//delete tmp;
		}
		iter = veci.erase(iter);
	}
    else
	{
          
   
		iter ++ ;
	}
}

2、clear清除数据出现假删除 容器中的数据没了,容器中的内存还在,也就是clear可以清除数据使容器size变成0,但不会是容器容量capacity变成0。 clear只会清楚容器中的元素。若元素为指针,指针托管的堆内对象的内存需要手动清理。

//元素类型T为原始指针时
for(vector<T>::iterator iter=veci.begin(); iter!=veci.end(); )
{
          
   
	T tmp = *iter;
	delete tmp;
	iter = veci.erase(iter);
}

//元素类型T为对象或一版类型时,智能指针类型为对象,而非真正的指针
for(vector<T>::iterator iter=veci.begin(); iter!=veci.end(); )
{
          
   
	iter = veci.erase(iter);
}
//与clear等效
veci.clear();
经验分享 程序员 微信小程序 职场和发展