静态 std::unordered_map 的默认值

Zac*_*Lee 9 c++ static dictionary initialization

我想知道 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';
}
Run Code Online (Sandbox Code Playgroud)

输出结果:

0
0
Program ended with exit code: 0
Run Code Online (Sandbox Code Playgroud)

认为内部Foo的变量总是0在开始时被初始化是否安全?

Hen*_*nke 17

是的,假设内部的值Foo总是初始化为零实际上是安全的,因为operator[]

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

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

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

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

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

    (使用 C++17if语句初始值设定项)

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

    std::cout << map.at("Apple").num << '\n';
    std::cout << map.at("Apple").state << '\n';
    
    Run Code Online (Sandbox Code Playgroud)

    这将使您的程序崩溃并出现std::out_of_range异常。您可能想捕获此异常以检查元素是否存在。不要这样做。将异常用于控制流是非常糟糕的做法。最重要的是,抛出异常时异常缓慢。