容器insert、erase操作引起迭代器失效問題

// insert、erase操作引起迭代器失效問題

#include "stdafx.h"
#include <iostream>
#include <list>
#include <vector>
#include <algorithm>

using namespace std;

void print_list(const list<int>& l)
{
	list<int>::const_iterator it;
	for(it=l.begin(); it!=l.end(); ++it)
	{
		cout<<*it<<ends;
	}
	cout<<endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	// 迭代器失效問題的解決方式:
	// 確保傳給insert、erase的迭代器在下次insert、erase操作時有效
	// 一般是將迭代器重置爲insert、erase返回值(再適當++、--)或者重新計算迭代器
	int a1[] = { 1,2,3,4,5 };
	int a2[] = { 1,2,6,7,8 };
	list<int> list1(a1, a1+sizeof(a1)/sizeof(a1[0]));
	list<int> list2(a2, a2+sizeof(a2)/sizeof(a2[0]));

	// 刪除list2中值屬於list1的元素(1,2)
	list<int>::iterator it;
	for(it=list1.begin(); it!=list1.end(); ++it)
	{
		auto pos = find(list2.begin(), list2.end(), *it);
		if(pos != list2.end())
		{
			list2.erase(pos);
		}
	}
	print_list(list2);

	// 在list2中插入屬於list1但不屬於list2的值(3,4,5)
	for(it=list1.begin(); it!=list1.end(); ++it)
	{
		auto pos = find(list2.begin(), list2.end(), *it);
		if(pos == list2.end())
		{
			// 每次pos都被重新定義和計算,無需重置pos爲返回值,雖然這次操作後當前pos失效
			list2.insert(pos, *it);
		}
	}
	print_list(list2);

	// 刪除list2中值不屬於list1的元素(6,7,8)
	for(it=list2.begin(); it!=list2.end(); )
	{
		auto pos = find(list1.begin(), list1.end(), *it);
		if(pos == list1.end())
		{
			// 注意迭代器失效問題,如果不保存it,it失效,則++it是未定義行爲,
			// it值必須同時改變爲返回值(刪除之後的迭代器)
			it = list2.erase(it); 
		}
		else
			++it;
	}
	print_list(list2);

	// 在list2中插入一次性5個屬於list1又屬於list2的值(1,2,3,4,5)
	for(it=list1.begin(); it!=list1.end(); ++it)
	{
		auto pos = find(list2.begin(), list2.end(), *it);
		if(pos != list2.end())
		{
			for(int i=0; i<5; ++i)
			{
				// 注意迭代器失效問題,如果不保存pos,pos失效第二次插入時pos已經失效
				// 在pos之前插入,返回指向新元素的迭代器(pos-1)
				pos = list2.insert(pos, *it); 
				// 確保每次在相同位置插入:第一次的pos之前
				++pos;
				// ++pos; // error! pos指向將不定
			}
		}
	}
	print_list(list2);

	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章