Reputation: 570
Suppose I have a map<string, vector<int>>
called my_map
and I want to associate 42
to the key "foo"
. Coming from Java I would expect to have to do something like this
if (my_map.find("foo") != my_map.end()) {
my_map["foo"].push_back(42);
} else {
vector<int> my_vector;
my_map["foo"] = my_vector;
my_vector.push_back(42);
}
To my surprise I found that I can just do
my_map["foo"].push_back(42);
How does this work? What would my_map["foo"]
do if the type of the map's values did not have a constructor with no parameters? Suppose you wanted to initialise all values in a manner other than using an empty constructor? In Java, I could do
map.computeIfAbsent("foo", **some supplier of Vectors**).add(42);
Is there an equivalent in C++?
Upvotes: 1
Views: 2091
Reputation: 63114
my_map["foo"]
default-constructs a new value if it doesn't already exist. Thus, it would cause a compilation error if the value type was not default-constructible (i.e. didn't have a constructor with no parameter). You would then have to do the following :
my_map.emplace("foo", param).first->second.push_back(42);
Where emplace
would construct your value from param
if it didn't already exist.
More parameters can be supplied with the piecewise constructor from std::pair
:
my_map.emplace(
std::piecewise_construct,
std::forward_as_tuple("foo"),
std::forward_as_tuple(param1, param2, param3)
).first->second.push_back(42);
Upvotes: 6
Reputation: 1899
You can read here for operator[]
:
If k does not match the key of any element in the container, the function inserts a new element with that key and returns a reference to its mapped value. Notice that this always increases the container size by one, even if no mapped value is assigned to the element (the element is constructed using its default constructor).
If the mapped_type
doesn't have a default constructor, you'd get a compilation error.
Upvotes: 2