C++迭代器失效问题

deque

添加元素

在中间添加

在deque的中间添加元素,所有的iterator/pointer/reference都将失效。

int main()
{
	deque<int> ideque{0,1,2,3,4,5};
	deque<int>::iterator iter_ideque_beg = ideque.begin();
	deque<int>::iterator iter_ideque_end = ideque.end() - 1;
	deque<int>::iterator iter_ideque_mid = ideque.begin() + ideque.size() / 2;
	int &rideque0 = ideque.front();
	int &rideque3 = ideque.at(3);
	int &rideque5 = ideque.at(5);
	int *pideque0 = &ideque.front();
	int *pideque3 = &ideque.at(3);
	int *pideque5 = &ideque.at(5);
	cout << "Before insert element in the middle: " << endl;
	cout << "*iter_ideque_beg = " << *iter_ideque_beg << endl;
	cout << "*iter_ideque_mid = " << *iter_ideque_mid << endl;
	cout << "*iter_ideque_end = " << *iter_ideque_end << endl;
	cout << "&rideque0 = " << rideque0 << endl;
	cout << "&rideque3 = " << rideque3 << endl;
	cout << "&rideque5 = " << rideque5 << endl;
	cout << "*pideque0 = " << *pideque0 << endl;
	cout << "*pideque3 = " << *pideque3 << endl;
	cout << "*pideque5 = " << *pideque5 << endl;
	// insert element in the middle
	ideque.insert(iter_ideque_mid, 9);
	cout << "After insert element in the middle: " << endl;
	// The following three statements are illegal, because iterators
	// are invalid after inserting elements in the middle (neither head
	// nor tail).
	// cout << "*iter_ideque_beg = " << *iter_ideque_beg << endl;
	// cout << "*iter_ideque_mid = " << *iter_ideque_mid << endl;
	// cout << "*iter_ideque_end = " << *iter_ideque_end << endl;
	cout << "&rideque0 = " << rideque0 << endl;
	cout << "&rideque3 = " << rideque3 << endl;
	cout << "&rideque5 = " << rideque5 << endl;
	cout << "*pideque0 = " << *pideque0 << endl;
	cout << "*pideque3 = " << *pideque3 << endl;
	cout << "*pideque5 = " << *pideque5 << endl;
	return 0;
}

运行结果为

Before insert element in the middle:
*iter_ideque_beg = 0
*iter_ideque_mid = 3
*iter_ideque_end = 5
&rideque0 = 0
&rideque3 = 3
&rideque5 = 5
*pideque0 = 0
*pideque3 = 3
*pideque5 = 5
After insert element in the middle:
&rideque0 = 1
&rideque3 = 3
&rideque5 = 5
*pideque0 = 1
*pideque3 = 3
*pideque5 = 5

上面的代码在deque的中间插入了一个元素9,之后尝试使用iterator的程序将会引起程序崩溃。虽然指针和引用还可以使用,不会引起程序崩溃,但是值已经不再是原来的值了。

在尾部插入

将插入代码改成下面的代码

ideque.insert(ideque.end(), 9);

运行结果为

Before insert element in the middle:
*iter_ideque_beg = 0
*iter_ideque_mid = 3
*iter_ideque_end = 5
&rideque0 = 0
&rideque3 = 3
&rideque5 = 5
*pideque0 = 0
*pideque3 = 3
*pideque5 = 5
After insert element in the end:
&rideque0 = 0
&rideque3 = 3
&rideque5 = 5
*pideque0 = 0
*pideque3 = 3
*pideque5 = 5

上面的代码在deque的尾部插入了一个元素9,之后尝试使用iterator的程序将会引起程序崩溃。指针和引用依旧有效(不会因此程序崩溃,而且值依旧是原来的值)。

在头部插入

将插入代码改成下面的代码

ideque.insert(ideque.begin(), 9);

运行结果和在尾部插入一样。

删除元素

从头部删除

ideque.erase(ideque.begin());

运行结果

 

Before insert element in the middle:
*iter_ideque_beg = 0
*iter_ideque_mid = 3
*iter_ideque_end = 5
&rideque0 = 0
&rideque3 = 3
&rideque5 = 5
*pideque0 = 0
*pideque3 = 3
*pideque5 = 5
After insert element in the end:
&rideque0 = 0
&rideque3 = 3
&rideque5 = 5
*pideque0 = 0
*pideque3 = 3
*pideque5 = 5

容器里没有0了,但是依旧可以使用指针和引用访问。迭代器失效,指针和引用有效。

在尾部删除

将删除代码改为

ideque.erase(ideque.end() - 1);

cout << "*iter_ideque_beg = " << *iter_ideque_beg << endl; // 并把这一个迭代器打开
cout << "*iter_ideque_mid = " << *iter_ideque_mid << endl; // 并把这一个迭代器打开

运行结果与

Before insert element in the middle:
*iter_ideque_beg = 0
*iter_ideque_mid = 3
*iter_ideque_end = 5
&rideque0 = 0
&rideque3 = 3
&rideque5 = 5
*pideque0 = 0
*pideque3 = 3
*pideque5 = 5
After delete element from the end:
*iter_ideque_beg = 0
*iter_ideque_mid = 3
&rideque0 = 0
&rideque3 = 3
&rideque5 = 5
*pideque0 = 0
*pideque3 = 3
*pideque5 = 5

从运行结果可以看出,引用和指针有效,删除点之前的迭代器有效。

从中间删除

将删除代码改为

ideque.erase(iter_ideque_mid);

引用和指针有效,删除点之前不包括删除点之前的迭代器有效。

总结

如果插入点位于除front和back的其它位置,iterators,pointers,references失效;当我们插入元素到front和back时,deque的迭代器失效,但reference和pointers有效;

如果删除点位于除front和back的其它位置,iterators,pointers,references失效;当我们删除元素到front和back时,off-the-end失效,其他的iterators,pointers,references有效;

发表评论

电子邮件地址不会被公开。 必填项已用*标注

3 × 1 =

+ 20 = 23