迭代器元素的删除

本文介绍了一个使用C++标准库中的vector容器及迭代器进行元素删除的例子。通过迭代器遍历容器并根据条件删除指定元素的过程中,需要注意迭代器的有效性更新,确保正确地跟踪已修改的容器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <iostream>
#include <vector>
using namespace std;
 
int main()
{
    vector<int> arr;
    arr.push_back(6);
    arr.push_back(7);
    arr.push_back(8);
    arr.push_back(9);

    for(vector<int>::iterator it=arr.begin(); it!=arr.end(); )
    {
        if(* it == 8)
        {
            it = arr.erase(it); //不能写成arr.erase(it);
        }
        else
        {
            ++it;
        }

在 C++ STL 中,使用迭代器删除容器元素时需要注意迭代器的失效问题。不同容器的删除操作对迭代器的影响不同,以下是常见容器的删除方法及注意事项: --- ### **1. 序列容器(`vector`、`deque`、`list`)** #### **(1) `std::vector` 和 `std::deque`** - **删除单个元素**: - 使用 `erase(iterator)`,返回指向被删除元素下一个位置的迭代器。 - **注意**:删除后原迭代器失效,必须使用返回的迭代器继续操作。 ```cpp std::vector<int> vec = {1, 2, 3, 4, 5}; auto it = vec.begin() + 2; // 指向 3 it = vec.erase(it); // 删除 3,it 指向 4 ``` - **删除范围**: - `erase(first, last)` 删除 `[first, last)` 范围内的元素,返回指向 `last` 的迭代器。 ```cpp auto first = vec.begin() + 1; // 指向 2 auto last = vec.begin() + 4; // 指向 5 first = vec.erase(first, last); // 删除 2,3,4,first 指向 5 ``` #### **(2) `std::list`** - **删除单个元素**: - `erase(iterator)` 返回下一个有效迭代器,原迭代器失效。 ```cpp std::list<int> lst = {1, 2, 3, 4, 5}; auto it = lst.begin(); // 指向 1 std::advance(it, 2); // 指向 3 it = lst.erase(it); // 删除 3,it 指向 4 ``` - **删除范围**: - 同 `vector`,`erase(first, last)` 返回 `last`。 ```cpp auto first = lst.begin(); // 指向 1 auto last = lst.begin(); std::advance(last, 3); // 指向 4 first = lst.erase(first, last); // 删除 1,2,3,first 指向 4 ``` --- ### **2. 关联容器(`set`、`map`、`multiset`、`multimap`)** - **删除单个元素**: - `erase(iterator)` 不返回迭代器(C++11 前),或返回 `void`(C++11 后)。 - **安全做法**:先递增迭代器删除。 ```cpp std::set<int> s = {1, 2, 3, 4, 5}; auto it = s.find(3); if (it != s.end()) { s.erase(it++); // 先复制 it 并递增,再删除原 it } ``` - **通过键删除**: - `erase(key)` 直接删除键对应的元素,无需迭代器。 ```cpp std::map<std::string, int> m = {{"Alice", 25}, {"Bob", 30}}; m.erase("Alice"); // 删除键为 "Alice" 的元素 ``` - **删除范围**: - `erase(first, last)` 删除 `[first, last)` 范围内的元素。 ```cpp auto first = s.begin(); auto last = s.begin(); std::advance(last, 2); s.erase(first, last); // 删除最小的 2 个元素 ``` --- ### **3. 无序关联容器(`unordered_set`、`unordered_map`)** - 行为与关联容器类似,但删除元素可能导致哈希表重组,**所有迭代器失效**(除非是删除的当前元素)。 - **安全做法**: ```cpp std::unordered_map<std::string, int> um = {{"Alice", 25}, {"Bob", 30}}; auto it = um.find("Alice"); if (it != um.end()) { um.erase(it); // 仅 it 失效,其他迭代器仍有效 } ``` --- ### **4. 通用删除模式** #### **(1) 循环中删除元素** - **错误示例**(`vector` 中直接删除导致迭代器失效): ```cpp for (auto it = vec.begin(); it != vec.end(); ++it) { if (*it % 2 == 0) { vec.erase(it); // 错误!it 失效后继续递增会导致未定义行为 } } ``` - **正确做法**: ```cpp for (auto it = vec.begin(); it != vec.end(); ) { if (*it % 2 == 0) { it = vec.erase(it); // 使用返回值更新迭代器 } else { ++it; } } ``` #### **(2) 使用 `erase_if`(C++20)** - 直接通过谓词删除元素,避免手动管理迭代器: ```cpp std::vector<int> vec = {1, 2, 3, 4, 5}; std::erase_if(vec, [](int x) { return x % 2 == 0; }); // 删除所有偶数 ``` --- ### **5. 关键注意事项** 1. **迭代器失效**: - `vector`/`deque`:删除后所有指向被删除元素之后的迭代器失效。 - `list`:仅被删除迭代器失效,其他不受影响。 - 关联/无序容器:通常仅被删除迭代器失效(但无序容器可能因哈希表重组影响其他迭代器)。 2. **性能考虑**: - `vector`/`deque` 的 `erase` 是 O(n) 操作(需要移动元素)。 - `list` 的 `erase` 是 O(1)。 - 关联容器的 `erase` 是 O(1)(平均)。 3. **C++11 后的改进**: - `map`/`set` 的 `erase` 返回下一个有效迭代器(C++11 起)。 --- ### **6. 代码示例汇总** #### **(1) `vector` 中删除偶数** ```cpp #include <vector> #include <iostream> int main() { std::vector<int> vec = {1, 2, 3, 4, 5, 6}; for (auto it = vec.begin(); it != vec.end(); ) { if (*it % 2 == 0) { it = vec.erase(it); } else { ++it; } } for (int x : vec) std::cout << x << " "; // 输出:1 3 5 } ``` #### **(2) `map` 中删除特定键** ```cpp #include <map> #include <iostream> int main() { std::map<std::string, int> m = {{"Alice", 25}, {"Bob", 30}, {"Charlie", 35}}; auto it = m.find("Bob"); if (it != m.end()) { m.erase(it); } for (const auto& [name, age] : m) { std::cout << name << ": " << age << std::endl; // 输出 Alice 和 Charlie } } ``` #### **(3) C++20 `erase_if` 简化操作** ```cpp #include <unordered_set> #include <iostream> int main() { std::unordered_set<int> s = {1, 2, 3, 4, 5}; std::erase_if(s, [](int x) { return x > 3; }); // 删除大于 3 的元素 for (int x : s) std::cout << x << " "; // 输出顺序可能为 1 2 3 } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值