三行代码  ›  专栏  ›  技术社区  ›  fluter

结束迭代器上的无序映射插入

  •  0
  • fluter  · 技术社区  · 3 年前

    find 找不到密钥时:

    auto it = m.find(key);
    if (it == m.end()) {
        m.insert(it, make_pair(key, value));
    }
    

    因为这将保存一个额外的查找比较使用:

    m[key] = value;
    
    0 回复  |  直到 3 年前
        1
  •  2
  •   Miles Budnek    3 年前

    虽然可以安全地将结束迭代器作为提示传递给 unordered_map::insert ,它实际上什么也做不了。

    在三个主要的标准库实现中,只有libstdc++使用该提示执行任何操作,即使这样,它也只能在指向有效条目时使用该提示。

    如果要避免执行两个查找(一个查找确定元素是否存在,另一个查找插入元素),则应尝试插入该元素。 insert 同时返回 bool

    decltype(m)::iterator it;
    bool inserted;
    std::tie(it, inserted) = m.insert(std::make_pair(key, value));
    if (inserted) {
        // ...
    }
    

    如果你的 mapped_type 建造起来很贵,你可以避免用 try_emplace (仅适用于C++ 17或更高版本):

    auto [it, inserted] = m.try_emplace(key, args, to, value, constructor);
    if (inserted) {
        // ...
    }
    

    前C + 17,你可以让 operator[]

    size_t size_before = m.size();
    ValueType& element = m[key];
    size_t size_after = m.size();
    if (size_before != size_after) {
        element = ValueType{args, to, value, constructor};
        // ...
    }
    

    显然,这有一个缺点,即默认构造元素,并且只处理可赋值类型。