10

如果我做:

std::map<string, size_t> word_count;
size_t value = word_count.count("a") == 0 ? 1 : 2;
word_count["a"] = value;

那么 word_count["a"] 的最终值为 1,正如我所料。相反,如果我这样做:

std::map<string, size_t> word_count;
word_count["a"] = word_count.count("a") == 0 ? 1 : 2;

那么 word_count["a"] 的最终值为 2。为什么!?

4

2 回答 2

11

正式地,可以首先评估任务的任何一方。由实施决定哪个。如果word_count不包含"a",则插入一个,并返回对它的左值引用。如果word_count确实包含一个,则只会发生后一部分。尽管不确定首先评估哪一方,但您可以遵循可能的执行:

左侧优先

不存在元素:

operator[]插入元素,因为它不存在。count()找到它并返回 1,所以你最终会被赋值为 2。

元素存在:

operator[]返回现有元素并count()找到它并返回 1,因此您最终会为它分配值 2。

右侧优先

不存在元素:

count()返回 0,所以你从右边得到 1。然后,"a"将 插入到映射中并分配值 1。

元素存在:

count()返回 1,所以你从右边得到 2。然后,word_count["a"]被访问并分配了 2 个。

结论

简而言之,你不能依赖这个来做你想做的事情,所以最好使用你可以依赖的东西。mrfontanini 提出了一个很好的建议,所以我会稍微编辑一下:

word_count["a"]++;
word_count["a"] = std::min(word_count["a"], 2);

第一行确保它已插入并且值至少为 1。第二行将该值限制为最大值 2,以防您重复执行此操作。

笔记

我根据两件事来回答这个问题:

  1. When a side is picked to be evaluated, the whole side has to be evaluated before the other side can start.

  2. 诸如此类的构造word_count["a"] = 1表现出明确定义的行为,即使在插入元素然后分配给它的情况下也是如此。

下面有一些关于这些是否属实的辩论和讨论。我现在更官方了。

于 2013-04-06T21:07:57.057 回答
5

看这一行:

word_count["a"] = word_count.count("a") == 0 ? 1 : 2;

相信如果word_count["a"]在执行该行之前地图中不存在,则会导致未定义的行为。

这是因为word_count["a"]如果一个条目不存在,将在映射中创建一个条目,这将改变word_count.count("a"). 我们也不需要在这两个调用之间进行排序..

于 2013-04-06T21:17:02.523 回答