C ++:有条件地将一个键和值插入到std :: map中

时间:2013-04-06 21:07:06

标签: c++

如果我这样做:

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.为什么!?

2 个答案:

答案 0 :(得分:10)

正式地说,可以首先评估任务的任何一方。由实现来决定哪个。如果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. 当选择一个侧面进行评估时,必须在另一侧开始之前对整个侧面进行评估。

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

  3. 下面有一些关于这些是否属实的辩论和讨论。我现在已经做了一点more official

答案 1 :(得分:4)

看看这一行:

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

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

这是因为word_count["a"]将在地图中创建一个条目(如果不存在),这将改变word_count.count("a")的行为。我们在这两个电话之间也没有必要的排序..