前言:

vector我们经常使用,对vector里面的基本函数构造函数、增加函数、删除函数、遍历函数我们也会用到。其中在使用遍历之后erase删除元素过程中,会出现一种删除最后一个元素破坏了迭代器的情况。

如下所示 删除到最后一个元素的时候就会报错

vector<int> data(10);
auto temp_begin = data.begin(), temp_end= data.end();
for(;temp_begin!=temp_end;){
data.erase(temp_begin);
}

产生这个问题的原因是:当我们调用erase方法删除元素的时候,erase方法会返回下一个元素的迭代器。当删除到最后一个元素的时候,这个时候返回的是最后一个元素之后的容器,而不是最后一个元素。

作者:良知犹存

转载授权以及围观:欢迎关注微信公众号:羽林君

或者添加作者个人微信:become_me


原因分析:

vector:

Because vectors keep an array format, erasing on positions other than the vector end also moves all the elements after the segment erased to their new positions, which may not be a method as efficient as erasing in other kinds of sequence containers (deque, list).

This invalidates all iterator and references to position (or first) and its subsequent elements.

假设你的 vector 中有多个对象,最后一个被标记为销毁。当您调用erase时,它将返回一个新的有效迭代器,该迭代器指向已删除元素之后的元素。被删除的元素之后没有元素,因此返回的迭代器为data.end()。

然后,我们继续循环的顶部并取消引用此迭代器,这是无效的。如果要让迭代器指向有效元素,则需要在擦除后减少其迭代器。

vec.end() 给你元素的迭代器以下容器的最后一个元素。看这里:

list和vector区别(list 这样删除就没事)

List:

This effectively reduces the list size by the number of elements removed, calling each element's destructor before.

lists are sequence containers specifically designed to be efficient inserting and removing elements in any position, even in the middle of the sequence. Compared to the other base sequence containers (vector and deque), lists are the most efficient container erasing at some position other than the beginning or the end of the sequence, and, unlike in these, all of the previously obtained iterators and references remain valid after the erasing operation and refer to the same elements they were referring before (except, naturally, for those referring to erased elements).

列表是序列容器,专门设计用于在任何位置高效插入和删除元素,甚至在序列的中间。list erase不会改变原来的iterator,所以不会出现像vector删除最后一个iterator后程序错误。

修改建议

下面修改的建议都是让vector的end迭代器可以一直更新,重新判断当前位置。

vector<int> data(10);
auto iter = 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是否为空的判断

if (!data.empty())
data.erase(vec.end() - 1);

另外我们也发现 vector 的 erase 需要整个vector 移动,这个代价十分高,所以尽量少用。若排序顺序不是很重要的话,可以和最后的那个item swap,然后删掉最后那个,这样可以显著的提高效率。

结语

这就是我分享的项目中一些vector使用,如果大家有更好的想法和需求,也欢迎大家加我好友交流分享哈。


作者:良知犹存,白天努力工作,晚上原创公号号主。公众号内容除了技术还有些人生感悟,一个认真输出内容的职场老司机,也是一个技术之外丰富生活的人,摄影、音乐 and 篮球。关注我,与我一起同行。

                                                ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

推荐阅读

【1】C++的智能指针你了解吗?

【2】嵌入式底层开发的软件框架简述

【3】CPU中的程序是怎么运行起来的 必读

【4】cartographer环境建立以及建图测试

【5】设计模式之简单工厂模式、工厂模式、抽象工厂模式的对比

本公众号全部原创干货已整理成一个目录,回复[ 资源 ]即可获得。

在开源项目或项目中使用git建立fork仓库的更多相关文章

  1. 如何使用Git建立本地仓库并上传代码到GitHub

    使用Git建立本地仓库并上传代码到GitHub 工具/原料   电脑安装git客户端.注册github账号并登陆 方法/步骤     到本地项目文件夹右键选择git bash here   输入个人信 ...

  2. VS.net 2013中使用Git建立源代码管理 版本管理

    第一次在VS2013中使用Git,也是第一次使用Git,各种不熟悉.百度各种使用经验,大都不屑于使用VS2013集成的Git,建议下载这个下载那个,我也照学了,确实能实现项目的提交.同步.合并的工作, ...

  3. [转]VS2013中使用Git建立源代码管理

    本文转自:https://blog.csdn.net/bodybo/article/details/38976549 第一次在VS2013中使用Git,也是第一次使用Git,各种不熟悉.百度各种使用经 ...

  4. VS2013中使用Git建立源代码管理

    原文:http://blog.csdn.net/bodybo/article/details/38976549/ 第一次在VS2013中使用Git,也是第一次使用git,各种不熟悉.百度各种使用经验, ...

  5. 项目实战--idea中使用Git遇到的坑

    问题 在一次代码的更新中,我按照以往的操作点,菜单中VCS下的Update Project,结果报错了,idea自动将我未提交的所有代码驻藏了stash了,全部代码还原了,心里慌了一下,去GitLab ...

  6. 使用git建立远程仓库,让别人git clone下来

    首先, 如果你的ssh没有安装的话,要安装ssh服务端.ubuntu是很简单 sudo apt-get install openssh-server 1,建立你的git 目录. ourunix@ubu ...

  7. 【Eclipse中使用Git之一】把远程仓库的项目,clone到eclipse里面

    [Eclipse中使用Git之一]把远程仓库的项目,clone到eclipse里面 2015-01-29 19:25 15779人阅读 评论(1) 收藏 举报 .embody{ padding:10p ...

  8. GitHub 上优秀的开源SLAM repo (更新中)

    GitHub 上优秀的开源SLAM repo (更新中) 欢迎 watch/star/fork 我们的 GitHub 仓库: Awesome-SLAM, 或者follow 项目的主页:Awesome- ...

  9. git初次建立远程仓库问题

    git "Could not read from remote repository.Please make sure you have the correct access rights. ...

随机推荐

  1. css - 样式 - 可见性

    visibility 可见性 取值:visible(可见) |  hidden(隐藏.保留占位) 设置给:块.行内块.行内元素 作用:设置元素在文档上的可见性 此属性只是隐藏元素,但会为元素保留占位. ...

  2. SpringBoot以jar包部署需要注意的thymeleaf页面映射问题

    关于themeleaf映射需要注意的: 1.页面映射 所有静态页面映射的时候,mapping后面要以/开头(最好),不以/开头也行 但是return 后面路径不能以/开头:IDE中正常,但是打jar包 ...

  3. Lyndon 相关的炫酷字符串科技

    浅谈从 Lyndon Words 到 Three Squares Lemma By zghtyarecrenj 本文包括:Lyndon Words & Significant Suffixes ...

  4. Linux制作Raid

    1.启动服务器 2.在服务器出现提示的时候,根据提示进入Raid管理界面(Ctrl + R),Raid管理界面如下: 3.删除原有的Raid 4.新建Raid 第一步:进入新建Raid的界面 第二步: ...

  5. 《DotNet Web应用单文件部署系列》二、打包wwwroot文件夹

    在这篇文章中,你将学到web缓存规则,文件传输中用到的压缩格式,以及如何手写代码响应请求.最后还能学到快速打包wwwroot文件夹组件用法. 一.了解Response Header 当第一次加载程序时 ...

  6. VueJS学习资料大全

    参考:http://www.worktle.com/articles/2467/ 文档&社区 Vue.js官方网站(中文) :http://cn.vuejs.org/ Vue论坛:http:/ ...

  7. 使用 elementUI 的表单进行查询,表单中只有一个文本框时,回车会自动触发表单的提交事件,导致页面的刷新。

    使用elementUI的el-form组件进行查询时,当输入框仅有一项时,回车自动提交表单,浏览器会刷新页面: 原因:由于当表单只有一个文本框时,按下回车将会触发表单的提交事件, 从而导致页面刷新. ...

  8. [PhpStorm]解决Cannot find declaration to go to

    1.问题重现 使用单例模式访问类方法,PhpStorm提示类方法Cannot find declaration to go to 2.解决方法 加一句代码注释 注意:注释不能省略变量名 注:成员变量实 ...

  9. mysql 基础配置经验

    创建库: 排序:utf8_unicode_ci和utf8_general_ci对中.英文来说没有实质的差别.utf8_general_ci校对速度快,但准确度稍差. 普遍的意思utf8_unicode ...

  10. 创建一个Orchard Core CMS 应用程序

    开始使用Orchard Core作为NuGet软件包 在本文中,我们将看到使用Orchard Core提供的NuGet包创建CMS Web应用程序是多么容易. 你可以在这里找到Chris Payne写 ...