关于vector的erase删除操作的两种不同方法,在linux与visual studio的实现讨论

关于vector的erase删除操作的两种不同方法,在linux与visual studio的实现讨论


1.前言:

最近在做某一个题时,用到了vector的删除操作,利用的是erase()函数删除符合条件的函数,然后和同学讨论的时候,同学给了一个写法,网上也搜到了一个写法,但是发现了问题。


2.测试代码:

定义一个vector 删除指定元素, 这里是删除1

#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector <int> arr; 
    arr.push_back(1);
    arr.push_back(2);
    arr.push_back(3);
    arr.push_back(4);
    arr.push_back(5);

    for (auto i = arr.begin(); i != arr.end(); i++) {           // 第一种写法
        if (*i == 1) {
            i = arr.erase(i);
            i--;
        }
    }

     for (auto i = arr.begin(); i != arr.end();) {           // 第二种写法
        if (*i == 1) {
            i = arr.erase(i);
        } else {
            i++;
        }
     }



    for (auto i = arr.begin(); i != arr.end(); i++) {        //输出
        cout << *i << " ";
    }
    cout << endl;



    return 0;
}

3.讨论


这两种写法, 看起来是基本相同的,基本想法就是每一次循环 删除了迭代器那么不自增迭代器,反之,则自增迭代器, 实则不然,如果一上来就删除首元素, 那么问题就来了 方法一的i在自减之后不是出了小于arr.begin()了吗。别急我们看下面的实践。


4.测试

ubuntu

在ubuntu下可以运行而且不出错
这里写图片描述

这里进入gdb调试 查看迭代器i的变化

这里写图片描述
**在删除元素后 迭代器自减后竟然是有地址的 此时地址是arr.begin()的前面一个地址, 也就是说i可以变成
arr.begin() - 1**

这里写图片描述
迭代器自加后 迭代器变成了arr.begin()

这里写图片描述

visual studio

运行时错误,出错在 i–;
因为i–后 i变成了arr.begin() - 1 而visual studio不支持这样的写法,所以报错
这里写图片描述

这里写图片描述

5.总结

vector如果简单想象成数组arr的话,在首元素i–,i = (arr - 1),但我们并没有在这个状态下解引用。然后i++加回去又回到可解引用的地址值,不出事也是可以理解的, gnu对list的实现是双向循环链表 ++list.end() 后就变成 list.begin()。但vs会assert说越界

posted @ 2017-04-25 10:20  qq874455953  阅读(236)  评论(0编辑  收藏  举报