C++用迭代器正确删除map元素

吃了这玩意的大亏,特此记录!


C++中删除map里的元素需要调用erase操作,但是错误的调用,会导致很多不可预支的问题,甚至于程序运行崩溃,不幸的是,楼主就遇到此情况,两天的Debug,结果发现仅是map删除元素时操作不当的问题!

一、在C++98前,erase操作

删除元素的操作是这样的

void erase (iterator position);
size_type erase (const key_type& k);
void erase (iterator first, iterator last);

用迭代器删除时,返回的是void。

二、在C++11后,的erase操作

就变成如下这样,返回的还是一个迭代器,且指向的删除后的下一个iter

iterator  erase (const_iterator position);
size_type erase (const key_type& k);
iterator  erase (const_iterator first, const_iterator last);

三、迭代器删除map中某一元素的正确用法

对于关联容器(如map, set, multimap,multiset),删除当前的iterator,仅仅会使当前的iterator失效,只要在erase时,递增当前iterator即可。

这是因为map之类的容器,使用了红黑树来实现,插入、删除一个结点不会对其他结点造成影响。

当然,C++11后,erase(iter)操作会返回下一个迭代器,因此就可以不需要递增了。

#include <iostream>
#include <map>

using namespace std;
int main() {
    map<int, string> m{{1, "one"}, {2, "two"},{3, "three"}, {4, "four"}, {5, "five"}};
    for(auto iter = m.begin(); iter != m.end();)
    {
        if (iter->first == 4)
        {
            iter = m.erase(iter);
        }
        else
            ++iter;
    }

    for(auto iter = m.begin(); iter != m.end(); iter++)
    {
        std::cout << iter->first <<" " << iter->second << std::endl;
    }
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

四、切记不可使用的方法(错误!错误!错误!)

下面这段看样子貌似非常正常的一 段代码。在一个map中寻找值为xxx的项并删除。但是实际上这个代码是完全错误的,会导致无法预料的结果。

因为对于关联容器(如map, set, multimap,multiset),删除当前的iterator,仅仅会使当前的iterator失效。

如果在不知情的情况下使用了失效的迭代器,后果是不可预料的。可能程序立即崩掉,也可能什么事都没有发生。崩掉了还算幸运,因为至少知道出了问题,不然有的受的。

好吧,博主在开发环境上一切正常,在部署环境上就崩溃了,一度怀疑部署环境有问题。

int main()
{
    map<int, string> m{{1, "one"},
                       {2, "two"},
                       {3, "three"},
                       {4, "four"},
                       {5, "five"},
                       {6, "three"}};
    for(auto  iter = m.begin(); iter != m.end(); ++iter)
    {
        if (iter->second == "four")
        {
            m.erase(iter);
        }
    }

    for(auto iter = m.begin(); iter != m.end(); iter++)
    {
        std::cout << iter->first <<" " << iter->second << std::endl;
    }
    std::cout << "Hello, World!" << std::endl;
    return 0;
}
C++中的map容器提供了一套丰富的迭代器支持,允许用户遍历map中的元素map迭代器是一种特殊的指针,它能够遍历map中的每一个键值对,而不会破坏map容器本身。以下是map迭代器的一些基本用法: 1. 创建迭代器:可以通过使用map的begin()和end()成员函数来获取指向map中第一个元素和最后一个元素之后位置的迭代器。 ```cpp #include <iostream> #include <map> int main() { std::map<int, std::string> myMap; // ... 插入一些键值对到map中 ... // 创建迭代器 std::map<int, std::string>::iterator it = myMap.begin(); std::map<int, std::string>::iterator it_end = myMap.end(); // 使用迭代器 for (; it != it_end; ++it) { // 访问键值对 int key = it->first; std::string value = it->second; std::cout << "Key: " << key << ", Value: " << value << std::endl; } return 0; } ``` 2. 迭代访问:通过迭代器可以访问map中的每个元素。使用解引用操作符(*)可以获取迭代器当前指向的键值对。 3. 迭代器递增:通过递增操作符(++)来移动迭代器到下一个元素。由于map是按照键的顺序存储的,所以迭代器也是按照这个顺序访问元素。 4. 使用const_iterator:如果不需要修改map中的元素,可以使用const_iterator。const_iterator只能用于读取元素,不能修改它们。 ```cpp std::map<int, std::string>::const_iterator cit = myMap.begin(); for (; cit != myMap.end(); ++cit) { // 只能读取,不能修改 } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值