参看如下这段代码,我们遍历一个vector,使用erase删除其中的一个元素
int a[3]={1,2, 3};
std::vector<int> a_vec(a, a+3);
std::vector<int>::iterator it;
printf("member before erase: ");
for(it = a_vec.begin(); it != a_vec.end(); it++)
{
printf("%d\t", *it);
if(*it == 2)
{
a_vec.erase(it);
}
}
printf("\n member after erase: ");
for(it = a_vec.begin(); it != a_vec.end(); it++)
{
printf("%d\t", *it);
}
printf("\n");
第一个for循环中当查找到元素2的时候,就把这个元素从vector中移除;然后第二个循环把删掉一个元素的vector打印出来;
我们期望的打印结果应该是这样的
member before erase: 1 2 3
member after erase: 1 3
然而,实际打印的时候,结果却是,
member before erase: 1 2
member after erase: 1 3
最后一个元素没有打印出来,这是什么原因呢?
这里我们尝试一下把所有的iterator的地址打印出来,0x30表示地址的后16bit
0x30(1) == 0x34(2) == 0x38(3) == 0x3C(end)
找到2的时候,it指向地址0x34,调用erase删除这个节点后,内存中存放就变成了如下这个样子
0x30(1) == 0x34(3) <- it == 0x38(end) ====
由于vector中存放的内容在地址上必须是连续的,所以实际上所有后面的元素都往前移了一个位置。
而迭代器it这个时候还是指向原来的0x34的位置,所以下一次for循环it就会指向end了。
所以在实际编码过程中要避免这种实现方式,因为如果找到你想删除的元素的时候it已经指向了最后元素了;删除了这个元素以后,it就会变成一个野指针,for循环会变成死循环。
网友评论