In C++ suppose I have an unordered map defined as follows:
unordered_map<int, MyClass> my_map;
auto my_class = my_map[1];
In the above code if 1 is not present as key in my_map it will initialize MyClass with default constructor and return. But is there a way to use non-default constructor of MyClass for initialization?
You're right that operator[]
needs the value type to be default-constructible.
insert
does not:
std::unordered_map<int, MyClass> my_map;
// Populate the map here
// Get element with key "1", creating a new one
// from the given value if it doesn't already exist
auto result = my_map.insert({1, <your value here>});
This gives you a pair containing an iterator to the element (whether created new, or already present), and a boolean (telling you which was the case).
So:
auto& my_class = *result.first;
const bool was_inserted = result.second;
Now you can do whatever you like with this information. Often you won't even care about result.second
and can just ignore it.
For more complex value types you can play around with emplace
, which is like insert
but, um, better. Say you really don't want the value to be constructed if it won't be used, and you have C++17:
auto result = my_map.try_emplace(1, <your value's ctor args here here>);
If you don't care (or don't have C++17):
auto result = my_map.emplace(1, <your value>);
This is still better than insert
as it can move the value into the map, rather than copying it.
Ultimately, and if you don't even want to unnecessarily produce your ctor args, you can always just do a find
first, but it's nice to try to avoid that, as the insertion operation itself will be doing a find too.
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