45

我有一个std::map这样的:

map<wstring,int> Scores;

它存储玩家的姓名和分数。当有人得分时,我会简单地做:

Scores[wstrPlayerName]++;

当地图中没有带有键的元素时,wstrPlayerName它将创建一个,但它是在增量之前初始化为零还是为空,还是未定义?

我应该在每次递增之前测试元素是否存在吗?

我只是想知道,因为我认为原始类型的东西在创建时总是未定义的。

如果我写类似:

int i;
i++;

编译器警告我 i 未定义,当我运行程序时它通常不为零。

4

4 回答 4

64

运算符 [] 看起来像这样:

Value& map<Key, Value>::operator[](const Key& key);

如果您使用尚未在地图中的键调用它,它将默认构造一个新的Value实例,将其放在您传入的下的地图中,并返回对它的引用。在这种情况下,您有:

map<wstring,int> Scores;
Scores[wstrPlayerName]++;

这里的值是int,并且 int 默认构造为 0,就好像您使用int()初始化它们一样。其他原始类型的初始化方式类似(例如double()long()、bool ()等)。

最后,您的代码将一个新对 (wstrPlayerName, 0) 放入地图中,然后返回对 int 的引用,然后您将其递增。因此,如果您希望事情从 0 开始,则无需测试该元素是否存在。

于 2009-02-03T17:11:36.970 回答
12

这将默认构造一个新的value. 对于整数,默认构造为 0,因此可以按预期工作。

于 2009-02-03T17:03:26.160 回答
5

在增加它之前,您不应该测试该项目是否存在。正如其他人所说, [] 运算符完全符合您的需要。

但是,如果默认构造的值对您不起作用怎么办?在您的情况下,查找元素是否已存在的最佳方法是尝试插入它。的insert成员函数std::map返回 a std::pair<iterator, bool>。无论插入成功还是失败,该对的第一个元素都将指向所需的对象(您的新对象或已经存在的对象)。然后,您可以根据需要更改其值。

于 2009-02-03T17:30:43.827 回答
1

检查初始化规则。

请参阅第 4.9.5 节 C++ Prog Lang 或 C++ 标准书的初始化。取决于您的变量是本地的、静态的、用户定义的还是 const 默认初始化。

在您的情况下, int 称为 POD(普通旧数据类型)。任何自动(在堆/局部变量上创建)POD 变量都不会默认初始化。因此,对您来说,上面的“i”的值不会为零。

在堆中定义时,始终养成初始化 POD 的习惯。您甚至可以使用 int() 来初始化值。

于 2009-02-03T17:49:44.693 回答