本文介绍了安全使用+ =操作符使用[]创建新的std :: map条目?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 std :: map< int,int> ,这样做是否安全?

Let's say I have a std::map<int, int>, would it be safe to do this?

std::map<int, int> m_map;
m_map[0] += 1;

如果键 0 不存在在地图中,当我这样做,它将如何知道要添加 1 到什么值?

If the key 0 didn't exist in the map when I do this, how would it know what value to add 1 to?

希望std :: map通过执行 = 而不是 + = 在地图中创建一个新条目。这将使我不必这样做:

What I'm hoping is that std::map handles this by performing an = instead of += in the case where the value creates a new entry in the map. This would spare me from having to do:

std::map<int, int>::iterator it = m_map.find(0);
if(it != m_map.end()) {
    it->second += 1;
}
else {
    m_map[0] = 1;
}


推荐答案

由于之前未映射的键是 值初始化 ,因此调用 operator [] 如果您没有看到该语法,请考虑以下代码段中的 () 的特殊含义。括号很重要。它们引入了一个不同于 default-initialization 的初始化树。两者都很重要;两者都是按语言标准规定的。

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();

事实证明,标量(包括指针)的值初始化最终会变成 零初始化 。虽然奇怪的看法,先前的片段值 - 初始化 int 的实例,其变为零初始化,因为 int 是标量,然后将其复制到 i

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;

或甚至:

++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;

a 成员映射到 0 在我们的容器中可以 1 之后执行? ,就是。另外,请考虑这一点:

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;

现在 S 构造函数(它必须,因为它必须构造 str )。但是在我们的容器中仍然 a 成员映射到 0 因此 1 之后的行)? ,就是。

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.

如果对引用的不同初始化路径感到好奇,请。或者查看C ++ 11标准,特别是 C ++ 11§8.5初始化程序(p5,p7,p10)。这是值得读的。

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.

这篇关于安全使用+ =操作符使用[]创建新的std :: map条目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-16 08:22