vector迭代器失效

vector 删除其中一个迭代器后,因后面数据移动,导致迭代器全部失效。有如下情况,一个迭代器指向其尾部元素,然后像后面添加元素(假定此时capacity>size),按理说迭代器不该失效,毕竟内存没有改变,但是VS17依然失效,求解释?

vector<int> vec;
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);
    vec.push_back(4);
    vec.push_back(5);
    vec.push_back(6);
    vec.push_back(7);
    cout << vec.size() << endl;   //7
    cout << vec.capacity() << endl;  // 9

    auto ite = vec.end();
    cout << &vec[0] << endl;

    vec.push_back(9);
    cout << &vec[0] << endl;  // same address
    auto it =  ite;
    //it--;   //invalid
全部评论
这个在vs2017-release模式(O2优化)下面根本没触发迭代器失效的。。。 你那个原因应该是在debug模式下,capacity是和size同步增长的,每次push_back都重新分配内存。这样最保险,因为这种***作确实有可能触发迭代器失效,所以debug模式用了最保险起见的办法保证一定触发。
点赞 回复
分享
发布于 2018-10-04 13:46
vector近身利器啊
点赞 回复
分享
发布于 2018-10-04 11:34
联易融
校招火热招聘中
官网直投
添加元素 尾部的迭代器当然失效了呀😂
点赞 回复
分享
发布于 2018-10-04 11:47
另外很容易看到,9是一个capacity,所以只有push到9个的时候才会触发重分配内存。 8个push的情况,可见能够正常访问: 9个push的情况,可见迭代器里剩的只是个野指针了,而且内存地址也发生了变换:
点赞 回复
分享
发布于 2018-10-04 13:53
代码呢
点赞 回复
分享
发布于 2018-10-04 11:26
内存地址没有改变是你打印地址之后得出的结论吗?
点赞 回复
分享
发布于 2018-10-04 11:27
尾部迭代器指向的是最后一个元素,而指向capacity的是另一个指针,插入尾部元素尾部迭代器当然要变化
点赞 回复
分享
发布于 2018-10-04 11:56
emm,添加尾部元素是会导致迭代器失效的吧
点赞 回复
分享
发布于 2018-10-04 11:58
是这样,虽然编译器没有给它重新分配地址,但是vs为了统一vector特性,索性仍然让该迭代器失效。这也许不是c++标准所规定的,但一定是vs编译器所规定的。
点赞 回复
分享
发布于 2018-10-04 11:59
尾部迭代器指向尾后元素,为了保证这一概念的正确性,即使添加元素并没有重新分配内存也会使尾后迭代器失效。至于迭代器如何感知,我想应该是通过判断size是否变化吧。
点赞 回复
分享
发布于 2018-10-04 12:04
统一回复下:既然指向尾后(not 尾部)元素,push_back后必然失效,如果指向尾部,那么就不会了(我自己也把这两个混淆了。。。)
点赞 回复
分享
发布于 2018-10-04 12:15
去看源码解析,你添加元素超过备用区的时候要重新开辟一块两倍大的空间,把你现在的内容复制过去,并且释放掉原空间,所有的迭代器都要失效
点赞 回复
分享
发布于 2018-10-04 13:00
这是release的反汇编,可见每次push并没有什么玄学***作,单纯做一个比较。 值得注意的是,rbp-0x18内存(对应size)里保存的是vec.end()的地址,而不是size的值。从mov的64位整数本身就可以看出这一点,add rbx, 4指令也可以看出。而capacity同理,保存了alloc的内存所允许的最后一个地址空间。 这是最后取end的时候,可见也没啥玄学***作,编译器反而很聪明地发现it经过++和--以后实际上一点都没动,所以直接把原来的end送给cout作为参数了(mov edx, dword ptr[rbx],*dx是thiscall要求的第一个整形参数,*cx是存this指针用的):
点赞 回复
分享
发布于 2018-10-04 14:21

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务