当前位置: 首页 > 科技观察

千万别被Vector的最后一个元素Erase弄错了

时间:2023-03-13 15:14:26 科技观察

前言:我们经常用到vector,我们也会用到vector中的基本函数构造函数,添加函数,删除函数,遍历函数。其中,在使用遍历后删除元素的过程中,会出现删除最后一个元素破坏迭代器的情况。删除最后一个元素会报错如下:vectordata(10);autotemp_begin=data.begin(),temp_end=data.end();for(;temp_begin!=temp_end;){data.erase(temp_begin);}出现这个问题的原因是:当我们调用erase方法删除一个元素时,erase方法会返回下一个元素的迭代器。当删除最后一个元素时,此时返回最后一个元素之后的容器,而不是最后一个元素。原因分析:vector:因为vector保持数组格式,在除vectorend之外的位置擦除也会将擦除后的段后的所有元素移动到新位置,这可能是一种不如其他类型序列容器中擦除效率高的方法(双端队列,列表)。这会使所有迭代器和对位置(或第一个)及其后续元素的引用无效。假设你的向量中有多个对象,最后一个被标记为销毁。当您调用擦除时,它会返回一个新的有效迭代器,该迭代器指向被删除元素之后的元素。被删除的元素后面没有元素,所以返回的迭代器是data.end()。然后我们继续到循环的顶部并取消引用这个无效的迭代器。如果你想让一个迭代器指向一个有效的元素,你需要在擦除之后递减它的迭代器。vec.end()为您提供指向以下容器的最后一个元素的元素迭代器。看这里:list和vector的区别(这样删除list没问题)删除任何位置的元素,即使是在序列的中间。与其他基本序列容器(vector和deque)相比,列表是在序列的开头或结尾以外的某个位置擦除的最有效的容器,并且与这些不同的是,所有先前获得的迭代器和引用仍然有效在擦除操作之后引用它们之前引用的相同元素(当然,那些引用已擦除元素的元素除外)。列表是序列容器,专门设计用于在任何位置高效地插入和删除元素,即使是在序列的中间。listerase不会改变原来的迭代器,所以删除最后一个迭代器后不会出现vector那样的程序错误。修改建议下面的修改建议是让vector的末尾迭代器一直更新,重新判断当前位置。vectordata(10);autoiter=data.begin();while(iter!=data.end()){data.erase(iter);}for(iter=data.begin();it!=data.end();){data.erase(iter);}将删除最后一个元素data.erase(data.end()-1);data.erase(data.begin()+data.size()-1);需要说明的是,如果vector为空,运行会崩溃,所以为了安全起见,我们可以再增加一个vector是否为空的判断if(!data.empty())data.erase(vec.end()-1);另外,我们还发现vector的擦除需要移动整个vector,开销很大,所以尽量少用。如果排序顺序不是很重要,可以和最后一项交换,删除最后一项,这样可以显着提高效率。结论这是我分享的项目中一些向量的使用。如果您有更好的想法和需求,欢迎加我好友一起交流分享。作者:还是有良心的,白天努力工作,晚上创建公众号主。公众号内容除了技术,还有一些生活感悟。一个认真输出内容的职场老司机,也是一个在科技、摄影、音乐、篮球之外丰富生活的人。跟随我,与我同行。