A while ago, I had a discussion with a colleague about how to insert values in STL maps. I preferred
map[key] = value;
because it feels natural and is clear to read whereas he preferred
map.insert(std::make_pair(key, value))
I just asked him and neither of us can remember the reason why insert is better, but I am sure it was not just a style preference rather there was a technical reason such as efficiency. The SGI STL reference simply says "Strictly speaking, this member function is unnecessary: it exists only for convenience."
Can anybody tell me that reason, or am I just dreaming that there is one?
Here's another example, showing that
operator[]
overwrites the value for the key if it exists, but.insert
does not overwrite the value if it exists.This is a rather restricted case, but judging from the comments I've received I think it's worth noting.
I've seen people in the past use maps in the form of
to evade cases of accidental value overwriting, but then go ahead writing in some other bits of code:
Their reason for doing this as I recall was because they were sure that in these certain bits of code they were not going to be overwriting map values; hence, going ahead with the more 'readable' method
[]
.I've never actually had any direct trouble from the code that was written by these people, but I strongly feel up until today that risks - however small - should not be taken when they can be easily avoided.
In cases where you're dealing with map values that absolutely must not be overwritten, use
insert
. Don't make exceptions merely for readability.insert
is better from the point of exception safety.The expression
map[key] = value
is actually two operations:map[key]
- creating a map element with default value.= value
- copying the value into that element.An exception may happen at the second step. As result the operation will be only partially done (a new element was added into map, but that element was not initialized with
value
). The situation when an operation is not complete, but the system state is modified, is called the operation with "side effect".insert
operation gives a strong guarantee, means it doesn't have side effects (https://en.wikipedia.org/wiki/Exception_safety).insert
is either completely done or it leaves the map in unmodified state.http://www.cplusplus.com/reference/map/map/insert/:
Another thing to note with
std::map
:myMap[nonExistingKey];
will create a new entry in the map, keyed tononExistingKey
initialized to a default value.This scared the hell out of me the first time I saw it (while banging my head against a nastly legacy bug). Wouldn't have expected it. To me, that looks like a get operation, and I didn't expect the "side-effect." Prefer
map.find()
when getting from your map.Now in c++11 I think that the best way to insert a pair in a STL map is:
The result will be a pair with:
First element (result.first), points to the pair inserted or point to the pair with this key if the key already exist.
Second element (result.second), true if the insertion was correct or false it something went wrong.
PS: If you don´t case about the order you can use std::unordered_map ;)
Thanks!
A gotcha with map::insert() is that it won't replace a value if the key already exists in the map. I've seen C++ code written by Java programmers where they have expected insert() to behave the same way as Map.put() in Java where values are replaced.