C++ 安全使用+;=运算符使用[]创建新的std::map条目?
假设我有一个C++ 安全使用+;=运算符使用[]创建新的std::map条目?,c++,map,C++,Map,假设我有一个std::map,这样做安全吗 std::map<int, int> m_map; m_map[0] += 1; 使用默认构造函数延迟初始化映射。(所有int为零) 所以它0在映射中不存在,它将被初始化为包含值0,1将添加到+=1之后 因此,您可以毫无顾虑地使用更高版本的代码 引用调用map_obj[k]的效果 如果k与容器中元素的键匹配,则函数 返回对其映射值的引用 如果k与容器中任何元素的键不匹配,则 函数使用该键插入新元素并返回引用 到它的映射值。请注意,这始终会
std::map
,这样做安全吗
std::map<int, int> m_map;
m_map[0] += 1;
使用默认构造函数延迟初始化映射。(所有int为零) 所以它
0
在映射中不存在,它将被初始化为包含值0,1将添加到+=1
之后
因此,您可以毫无顾虑地使用更高版本的代码
引用调用map_obj[k]的效果
如果k与容器中元素的键匹配,则函数
返回对其映射值的引用
如果k与容器中任何元素的键不匹配,则
函数使用该键插入新元素并返回引用
到它的映射值。请注意,这始终会增加容器的容量
大小为1,即使没有为元素指定映射值(
元素是使用其默认构造函数构造的)
是,这很好,新条目默认为value
value\u type()
,对于int
,它是0
它仍然提供
+=
,但是0+=1
提供1
即使使用较短的代码片段,也可以保证得到1
关键是操作符[]
必须在返回对元素的引用之前在映射中创建元素,因此当您到达+=
时,元素已经存在,如果必须现在创建,则值为零(因为映射的元素是值初始化的)
(顺便提一下,这就是为什么在使用类类型作为值的
std::map
时,如果要使用操作符[]
,即使您立即为其指定了对象,它也必须具有默认构造函数的原因)在调用操作符[]时插入到映射中的元素
由于先前未映射的键已初始化值。如果您没有看到该语法,请考虑下面的代码片段中的<强> <代码>(/)>代码> <强>的特殊含义。帕伦夫妇很重要。它们在初始化树中引入了与默认初始化不同的跳闸。两者都很重要;这两种语言都是按照语言标准制定的
int i = int();
事实证明,标量(包括指针)的值初始化最终屈从于零初始化。尽管看起来很奇怪,但前面的代码段值初始化了int
的一个实例,由于int
是一个标量,因此初始化为零,然后将其复制到i
。(平心而论,几乎肯定会有一些例外,但基本面是如此)
无论如何,由于该功能,您在执行此操作时可以放心:
m_map[0] += 1;
甚至这个:
++m_map[0];
如果之前没有映射索引,则会添加一个值初始化元素,这将为标量初始化零,这意味着您将正式从零开始
值得一提的是,对于具有隐式声明构造函数的任何类型,都会发生类似的活动。不管琐碎与否,都会发生有趣的事情
struct S { int a; int b; };
std::map<int, S> mymap;
++mymap[0].a;
现在S
有一个非平凡的隐式构造函数(它必须,因为它必须构造str
)。但是在我们的容器中映射到0
的a
成员是否仍然可靠地初始化为零(因此,1
位于上述行之后)是的,是的
如果对引用的不同初始化路径感到好奇。或者查看C++11标准,尤其是C++11§8.5初始值设定项(p5、p7、p10)。值得一读。可能重复:
struct S { int a; int b; };
std::map<int, S> mymap;
++mymap[0].a;
struct S { int a; std::string str; };
std::map<int, S> mymap;
++mymap[0].a;