Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 安全使用+;=运算符使用[]创建新的std::map条目?_C++_Map - Fatal编程技术网

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;