江苏齐力建设集团网站,用html5做手机网站,网站切片怎么做,微信小程序开发定制公司一、迭代器#xff1a;
迭代器的主要作用就是让算法能够不用关心底层数据结构#xff0c;其底层实际就是一个指针#xff0c;或者是对指针进行了封装#xff0c;比如#xff1a;vector的迭代器就是原生态指针T* 。因此迭代器失效#xff0c;实际就是迭代器底层对应指针所…一、迭代器
迭代器的主要作用就是让算法能够不用关心底层数据结构其底层实际就是一个指针或者是对指针进行了封装比如vector的迭代器就是原生态指针T* 。因此迭代器失效实际就是迭代器底层对应指针所指向的空间被销毁了而使用一块已经被释放的空间造成的后果是程序崩溃(即如果继续使用已经失效的迭代器程序可能会崩溃)。
二、vector原理 根据上图可知vector容器的成员变量主要有迭代器_start、迭代器_finish、迭代器_end_of_storage。迭代器_start指向的是vector里存第一个有效数据的位置迭代器_finish指向的是vector里存放的最后一个有效数据位置的下一个位置迭代器_end_of_storage指向的是vector里容量capacity的下一个位置。可以用_finish_end_of_storage判断vector容器的容量是否已满。 对于vector迭代器失效问题主要发生在插入insert、删除erase两个函数接口中。 对于resize、reserve、insert、assign、push_back等函数接口也会导致失效。 三、插入失效 因为在insert时vector可能需要进行扩容而扩容的本质是new一块新的空间再将数据迁移过去。而我们知道迭代器的本质是指针而插入后若vector扩容则原有的数据被释放指向原有数据的迭代器就成了野指针所以迭代器失效了。
int main(){vectorint v{ 1,2,3,4,5,6 };auto it v.begin();// 插入元素期间可能会引起扩容而导致原空间被释放v.insert(v.begin(), 0);while (it ! v.end()){cout *it ;it;}cout endl;return 0;}/*出错原因以上操作都有可能会导致vector扩容也就是说vector底层原理旧空间被释放掉而在打印时it还使用的是释放之间的旧空间在对it迭代器操作时实际操作的是一块已经被释放的空间而引起代码运行时崩溃。解决方式在以上操作完成之后如果想要继续通过迭代器操作vector中的元素只需给it重新赋值即可。*/ 解决方式让insert函数带一个返回值返回出插入元素后改元素的迭代器位置在使用改迭代器就不会造成野指针发生失效的问题了。
四、erase失效
using namespace std;
int main()
{int a[] { 1, 2, 3, 4 };vectorint v(a, a sizeof(a) / sizeof(int));//将数组a的元素放入v中// 使用find查找3所在位置的iteratorvectorint::iterator pos find(v.begin(), v.end(), 3);// 删除pos位置的数据导致pos迭代器失效。v.erase(pos);cout *pos endl; // 此处会导致非法访问return 0;
} erase删除pos位置元素后pos位置之后的元素会往前搬移没有导致底层空间的改变理论上讲迭代器不应该会失效但是如果pos刚好是最后一个元素删完之后pos刚好是end的位置而end位置是没有元素的那么pos就失效了。因此删除vector中任意位置上元素时vs就认为该位置迭代器失效了。 删除pos位置后pos迭代器就失效了不能再使用它。为解决这个问题同样可以使用返回值返回pos迭代器的下一个位置即4的位置在使用就不会访问错误了。 结论insert/erase 的pos为位置一定不要直接访问一定要更新直接访问可能会出现各种出乎意料的结果这就是所谓的迭代器失效。不要直接访问-不要直接访问-不要直接访问