An element inserted into a map on invoke of operator[]
due to a previously-unmapped key is value-initialized. If you've not seen that syntax, consider the special meaning the ()
has in the following code snippet. The parens are important. They introduce an different trip down the initialization tree than default-initialization. Both are important; both are laid out by the language standard.
int i = int();
As it turns out, value initialization for scalars (including pointers) eventually succumbs to zero-initialization. Though odd looking, the prior snippet value-initializes an instance of int
, which becomes zero-initialization since int
is a scalar, then copies it to i
. (To be fair, there will almost certainly be some eliding, but the fundamentals are as-presented).
Regardless, due to that feature, you can rest assured when you do this:
m_map[0] += 1;
or even this:
++m_map[0];
if the index wasn't mapped prior, a value-initialized element is added, which will zero-initialize for scalars, which means you'll officially starting out with zero.
It is worth mentioning that a similar activity happens for any type with an implicitly declared constructor. Whether trivial or not, something interesting happens.
struct S { int a; int b; };
std::map<int, S> mymap;
++mymap[0].a;
Is the a
member mapped to 0
in our container reliably 1
after the above executes? Yes, it is. Further, consider this:
struct S { int a; std::string str; };
std::map<int, S> mymap;
++mymap[0].a;
Now S
has a non-trivial implicit constructor (it has to, as it must construct str
). But is the a
member mapped to 0
in our container still reliably zero-initialized (and therefore 1
after the above line)? Yes, it is.
If curious about the referenced different paths of initialization, see this question and answer. Or review the C++11 standard, particularly C++11 § 8.5 Initializers, (p5,p7,p10). It is worth the read.