首页 > 解决方案 > 静态 std::unordered_map 的默认值

问题描述

我想知道 static 结构中变量的默认值static std::unordered_map<std::string, struct>

这是我的示例代码:

#include <iostream>
#include <string>
#include <unordered_map>

int main()
{
    enum MyStateType
    {
        MY_STATE_NEW,
        MY_STATE_RUN,
        MY_STATE_FREE
    };
    struct Foo
    {
        int num;
        MyStateType state;
    };
    static std::unordered_map<std::string, Foo> map;

    std::cout << map["Apple"].num << '\n';
    std::cout << map["Apple"].state << '\n';
}

输出结果:

0
0
Program ended with exit code: 0

认为里面的变量Foo总是0在一开始就被初始化是否安全?

标签: c++dictionarystaticinitialization

解决方案


是的,实际上可以安全地假设里面的值Foo总是初始化为零,因为operator[]

当使用默认分配器时,这将导致键被复制/移动从键构造并且映射的值被值初始化。

您不提供构造函数,这意味着Foo将单独初始化每个字段的值,这对于原始类型意味着零初始化。

"Apple"您在这里实际面临的问题是您的地图中不存在名为的字段。operator[]不幸的是,如果该值不存在,那么它的语义就是动态创建的。您可能甚至不想访问地图中不存在的字段,而是询问它是否始终初始化为零,以便您可以使用此事实来检查元素是否存在。但是,为此目的,您应该使用find()orat()成员函数。

  • find()如果元素不存在,将返回一个指向地图末尾的迭代器。这意味着您可以使用保护元素访问

    if (auto apple = map.find("Apple"); apple != map.end()) {
        std::cout << apple->second.num << '\n';
        std::cout << apple->second.state << '\n';
    }
    

    (使用 C++17if语句初始化程序)

  • at()如果未找到该元素,将抛出异常。

    std::cout << map.at("Apple").num << '\n';
    std::cout << map.at("Apple").state << '\n';
    

    这将使您的程序崩溃并出现std::out_of_range异常。您可能会想捕捉这个异常来检查元素是否存在。不要这样做。对控制流使用异常是非常糟糕的做法。最重要的是,当它们被抛出时,它们的速度非常慢。


推荐阅读