`

STL中erase()小心使用

    博客分类:
  • c++
 
阅读更多

via: http://blog.sina.com.cn/s/blog_67b6b720010114d3.html

 

erase()函数的功能是用来删除容器中的元素
删除某个容器里的某个元素:c.erase(T);
看似一个简单的动作,然而对不同类型的容器,内部却做了截然不同的事情,后面介绍。

假设有这样一个题目,将某个容器中所有满足条件N == X的元素删除,按照常规的思路应该有类似这样的代码:

// 假设Container和container分别表示一种容器和对应的一个对象
Container<T>::iterator it;
for (it = container.begin(); it != container.end(); ++it) {
  
if (N == X)
    container.erase(it);
}

然而这样的代码对于任一种容器都是错误的STL中erase()小心使用

容器按内存分配方式可以分为链表容器和数组容器。

所谓的链表容器指的是一种表现方式,包括list、slist等这样基于节点的容器 (动态分配内存块)和set、map、multiset、multimap等关联容器(平衡树实现),而数组容器指的是在一块连续的内存上保存元素的连续 内存容器,比如vector、deque、string等。

链表容器以list为例,当执行container.erase(it)时,确实第一 个满足条件的元素删除了,但这时it指针已经被删除了,它也不指向任何元素了,所以也只能到此为止了,也就是说上面的代码对于链表容器来说只能正确删除第 一个满足条件的元素,针对这个问题我们首先想到的就是在删除指针之前,给其做个备份。

将这个临时变量直接建立在erase实现里,这样做更简洁,也显得专业些。

list<int>::iterator it; 
  
for (it = lt.begin(); it != lt.end(); ) {
    
if (*it % 2 == 0)
      lt.erase(it
++); //这里是关键
    
else
      
++it;
  }

 

链表容器使用erase删除节点还有一个特点,就是会将下一个元素的地址返回,所以也可以这样实现:

list<int>::iterator it; 
  
for (it = lt.begin(); it != lt.end(); ) {
    
if (*it % 2 == 0)
      it 
= lt.erase(it);//自动返回下一个元素的地址,不用再主动前移指针
    
else
      
++it;
  }

 

数组容器以vector为例,当执行container.erase(it)时,和上面提到的一样,第一个满足条件的元素删除了,但这时数组容器不允许中间有“空隙”,所以会做个大动作,就是将被删元素后面所有的元素前移(参考STL源码),而数组容器记录的是下标,所以删除元素后,当前下标定位的元素也就顺理成章的变成了原有队列中的下一个元素,同样以删除偶数为例,代码如下:

vector<int>::iterator it = v.begin();
  
for (it = v.begin(); it != v.end(); ) { 
    
if (*it % 2 == 0)
      v.erase(it);//删除元素后,后面元素自动往前移,不用挪动指                  
    
else
      
++it;
  }
 网上有说在VS2005里面上面的v.erase(it)写法是行的  VS2008及2010却运行会出现错误 会出现
vector erase iterator outside range  最保险的做法是
将v.erase(it)改成 it=v.erase(it) 

分享到:
评论

相关推荐

    stl容器set,map,vector之erase用法与返回值详细解析

    在示例代码中,两种删除方式都是安全的,但使用索引删除(方法2)时,要注意在删除元素后,后面的索引会向前移动,因此在循环中需要小心处理索引递增。 在遍历`vector`并删除元素时,需要注意以下几点: - 使用迭代...

    effective stl stl 技巧

    - 在多线程环境中使用STL时,采取额外措施确保线程安全。 #### vector和string #### 条款13:尽量使用vector和string来代替动态分配的数组 - **核心概念**:`vector`和`string`提供了更安全、更高效的动态数组...

    Effective STL(中文)

    在删除选项中仔细选择 条款10:注意分配器的协定和约束 条款11:理解自定义分配器的正确用法 条款12:对STL容器线程安全性的期待现实一些 vector和string 条款13:尽量使用vector和string来代替动态...

    Effictive STL CHM中文版

    条款32: 如果你真的想删除东西的话在remove-like的算法后紧接上erase 条款33: 当心在包含指针的容器使用remove-like的算法 条款34: 注意哪些算法需要排序过的范围 条款35: 通过mismatch或lexicographical_compare...

    Effective STL.zip

    8. **条款8:使用`std::bind1st`和`std::bind2nd`固定函数参数** —— 这些工具可以创建偏函数对象,固定传给函数的第一个或第二个参数,便于在STL算法中使用。 9. **条款9:考虑使用`std::equal_range`而非`std::...

    AW - Effective STL

    自定义分配器可以在特定情况下提高性能,例如在多线程环境中减少锁的竞争,或在内存受限的系统中优化内存使用。但是,过度使用自定义分配器也可能带来维护和性能问题。 **Item 12: 对 STL 容器的线程安全性要有现实...

    Effective STL

    ### Effective STL - 关键知识点概览 ...以上是《Effective STL》一书中部分关键知识点的总结,旨在帮助读者更好地理解和应用STL库中的各种容器、迭代器和算法。希望这份概览能够为您的学习之旅提供有价值的指导。

    c++pdf.zip

    6. **理解迭代器失效**:某些操作(如push_back、erase等)可能导致迭代器失效,必须小心处理。 **《More Effective C++》** 这本书扩展了前两本的主题,包含35个新条款: 1. **使用异常安全编程**:异常可能会...

    c++中vector的用法详解-vector类用法.docx

    `vector`是C++标准模板库(STL)中的一个重要容器,它提供了一种类似于动态数组的数据结构。与传统数组相比,`vector`能够自动调整其大小以适应数据的需求变化,这使得它成为处理未知或可变长度数据序列的理想选择。 ...

    C++新手笔记

    在程序数组使用中,指标(索引)的处理必须格外小心,因为错误的索引可能会导致越界访问,进而引发运行时错误或程序崩溃。 对于浮点数的比较,直接使用`==`或`!=`是比较危险的,因为浮点数的计算可能受到精度损失的...

    (转)一个优秀的C++学习笔记

    - **在`remove`算法之后调用`erase`**:通常情况下,先使用`remove`算法将元素移到容器末尾,然后使用`erase`移除这些元素。 - **对包含指针的容器使用`remove`算法时要特别小心**:处理指针时,需要额外注意内存...

    ArrayList的一个C++类模板实现

    在Java中,ArrayList是基于数组实现的,而在C++中,我们通常使用std::vector来达到类似的效果。然而,对于大规模数据,简单的数组或vector可能会遇到性能瓶颈,特别是在插入和删除元素时,因为它们可能需要移动大量...

    C C++面试题

    - 在删除容器中的元素时,需要特别小心,以避免无效迭代器的使用。在这个例子中,`array.erase(itor)` 删除了当前迭代器所指向的元素,使得后续的 `++itor` 操作指向了一个无效的位置。为了避免这个问题,可以在循环...

Global site tag (gtag.js) - Google Analytics