C++ unordered_map<T, int>如何区分空单元格和0

C++ unordered_map<T, int> how to distinguish null cell from 0

假设我有一个 unordered_map<string, int> H

假设 H 中没有元素 "house",因此 cout<<H["house"]; 将打印 0。

但是假设我需要分配 H["house"] = 0

如何区分不存在的元素和 0 的元素?

//example of what I want:

if(!H["house"]){
    cout<<"DOES NOT EXIST YET\n";
    H["house"] = 0;
}

if(H["house"]){
    cout<<"IT EXISTS NOW\n";
}

std::unordered_map 中,如果元素不存在,operator[] 修改映射。这是为了允许像 H["house"] = 0 这样的简单赋值语句起作用。查的时候真的不要这个

相反,您应该使用 H.find,或使用 H.atfind returns 一个迭代器,如果找不到元素,它将与 H.end() 进行比较,否则可以取消引用该值。 at 如果找不到该元素,则抛出错误。

auto itr = H.find("house");
if (itr == H.end())
{
    // "house" does not exist in H
}
else
{
    // "house" exists
    // itr->second = the same as H["house"]
}

最短测试:

if (H.count("house")) {
    // "house" exists
} else {
    // "house" does not exist in H
}

如果您有权访问 boost,那么 return 对映射类型的可选引用的一个小函数可能会有用。如果你有最近的 c++ 实现,你可以使用 std::optional.

template<class K, class V, class H, class E, class A, class Lookup>
auto 
maybe_at(std::unordered_map<K,V,H,E,A> const& m, Lookup&& key)
-> boost::optional<V const&>
{
    boost::optional<V const&> result;
    auto i = m.find(key);
    if (i != m.end())
        result = i->second;
    return result;
}

使用示例:

#include <unordered_map>
#include <boost/optional.hpp>
#include <iostream>
#include <string>

template<class K, class V, class H, class E, class A, class Lookup>
auto 
maybe_at(std::unordered_map<K,V,H,E,A> const& m, Lookup&& key)
-> boost::optional<V const&>
{
    boost::optional<V const&> result;
    auto i = m.find(key);
    if (i != m.end())
        result = i->second;
    return result;
}

void emit(boost::optional<const int&> oi)
{
    if (oi)
    {
        std::cout << *oi << std::endl;
    }
    else
    {
        std::cout << "{null}" << std::endl;
    }
}

int main()
{
    std::unordered_map<std::string, int> m;

    m["house"] = 0;

    emit(maybe_at(m, "house"));
    emit(maybe_at(m, "donkey"));
}