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?
As you might expect, an unordered_map returns the default value for the value type if the key is not found in the map (count[5] will return 0 in this case).
The value object is value-initialized, not zero-initialized.
std::unordered_map::unordered_map Constructs an empty unordered_map object, containing no elements and with a size of zero.
To initialize the map with a random default value below is the approach: Approach: Declare a structure(say struct node) with a default value. Initialize Map with key mapped to struct node.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With