映射::擦除:按键擦除或迭代器擦除之间的区别

map::erase: difference between erase by key or by iterator?

本文关键字:擦除 之间 区别 迭代器 映射      更新时间:2023-10-16

如果我想从映射中删除单个元素(除了可能的错误检查之外,我不关心返回值),有两种方法可以:按键erase或按值erase

http://ideone.com/YWocN7

#include <iostream>
#include <map>
using namespace std;
void printMap(const std::map<int, double>& m)
{
    for (auto kv : m)
    {
        std::cout << '{' << kv.first << ", " << kv.second << '}';
    }
    std::cout << 'n';
}
int main() {
    std::cout << "erase by iterator:n";
    std::map<int, double> m1 = { { 1, 1.1 }, { 2, 2.2 }, { 3, 3.3 } };
    printMap(m1);
    m1.erase(m1.find(2));
    printMap(m1);
    std::cout << "erase by key:n";
    std::map<int, double> m2 = { { 1, 1.1 }, { 2, 2.2 }, { 3, 3.3 } };
    printMap(m2);
    m2.erase(2);
    printMap(m2);
    return 0;
}

输出:

erase by iterator:
{1, 1.1}{2, 2.2}{3, 3.3}
{1, 1.1}{3, 3.3}
erase by key:
{1, 1.1}{2, 2.2}{3, 3.3}
{1, 1.1}{3, 3.3}

这两种方法是否完全等效,或者是否有任何实际原因或情况使我可能更喜欢其中一种方法

在您描述的场景中( m1.erase(2); vs. m1.erase(m1.find(2)); ),这两种方法应该是完全等价的,给出或承担创建和返回迭代器的成本,尽管这取决于您的 STL 实现。
erase by iterator的要点是从键中删除条目,当您已经有一个迭代器时,因为您的程序需要在此迭代器引用的元素上执行其他操作。例如:

void processEntry(const std::pair<int, double>& p) {
     // do something like maybe writing it to a file
}
std::map<int, double> m1 = { { 1, 1.1 }, { 2, 2.2 }, { 3, 3.3 } };
const auto it = std::find_if(m1.begin(), m1.end(), [](const std::pair<int, double>& p) {
    return p.first > 1 && p.second < 3.0;
});
if (it != m1.end()) {
    processEntry(*it);
    m1.erase(it);
}

地图擦除支持以不同的方式擦除 elemnt,如下所示

void erase( iterator pos );
iterator erase( const_iterator pos );
void erase( iterator first, iterator last );
iterator erase( const_iterator first, const_iterator last );        
size_type erase( const key_type& key );

在您的情况下,您使用的是 erase( 迭代器) 和 erase( const key_type),即使这两个操作的结果相同,操作的执行方式也可能不同。

erase( const key_type& key );会找到钥匙,然后擦除它。

erase( iterator)已经有想要擦除元素的位置