简体   繁体   中英

Default value of static std::unordered_map

I would like to know the default value of variables inside a struct of static static std::unordered_map<std::string, struct> .

Here's my example code:

#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';
}

The output result:

0
0
Program ended with exit code: 0

Is it safe to think that variables inside Foo are always initialized to 0 in the beginning?

Yes, it is actually safe to assume that the values inside Foo are always initialized to zero because of the behaviour of operator[]

When the default allocator is used, this results in the key being copy/move constructed from key and the mapped value being value-initialized.

You do not provide a constructor which means that each field in Foo will be value initialized individually which for primitive types means zero initialization.

but

The problem you are actually facing here is that a field called "Apple" does not exist in your map. Unfortunately the semantics of operator[] are such that if the value does not exist, it will be created on the fly. You probably didn't even want to access a non-existent field in the map and you are asking whether it is always initialized to zero so that you can use this fact to check whether the element was there. For this purpose however, you should either use the find() or at() member function.

  • find() will return an iterator pointing to the end of the map if the element does not exist. That means you could guards the element access using

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

    (with the C++17 if statement initializer)

  • at() will throw an exception if the element is not found.

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

    This will crash your program with a std::out_of_range exception. You might feel temped to catch this exception to check whether the element existed. Don't do this. It is very bad practice to use exceptions for control flow. On top of that exception are dead slow when they are being thrown.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM