由于先前未映射的键而在调用 operator[] 时插入到映射中的元素是值初始化。如果您还没有看到该语法,请考虑 () 在以下代码 sn-p 中的特殊含义。括号很重要。它们在初始化树中引入了不同于 default-initialization 的旅程。两者都很重要;两者都由语言标准规定。
int i = int();
事实证明,标量(包括指针)的值初始化最终会屈服于零初始化。虽然看起来很奇怪,但之前的 sn-p 值初始化了一个 int 的实例,由于 int 是一个标量,它变成了零初始化,然后将其复制到 i。 (公平地说,几乎可以肯定会有一些省略,但基本面如前所述)。
无论如何,由于该功能,您可以放心:
m_map[0] += 1;
甚至这个:
++m_map[0];
如果之前未映射索引,则会添加一个值初始化元素,该元素将对标量进行零初始化,这意味着您将正式从 零 开始。
值得一提的是,对于具有隐式声明的构造函数的任何类型,都会发生类似的活动。不管是不是微不足道的事情,都会发生一些有趣的事情。
struct S { int a; int b; };
std::map<int, S> mymap;
++mymap[0].a;
上述执行后,a 成员是否可靠地映射到我们容器中的0 1? 是的,是的。此外,考虑一下:
struct S { int a; std::string str; };
std::map<int, S> mymap;
++mymap[0].a;
现在S 有一个重要的隐式构造函数(它必须,因为它必须构造str)。但是a 成员是否映射到我们容器中的0仍然可靠地进行零初始化(因此1 在上述行之后)? 是的,是的。
如果对引用的不同初始化路径感到好奇,see this question and answer。或者查看 C++11 标准,特别是 C++11 § 8.5 Initializers, (p5,p7,p10)。值得一读。