如果我这样做:
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.为什么!?
答案 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,如果重复执行此操作。
我的答案基于两件事:
当选择一个侧面进行评估时,必须在另一侧开始之前对整个侧面进行评估。
word_count["a"] = 1
之类的构造表现出明确定义的行为,即使在插入元素然后分配给元素的情况下也是如此。
下面有一些关于这些是否属实的辩论和讨论。我现在已经做了一点more official。
答案 1 :(得分:4)
看看这一行:
word_count["a"] = word_count.count("a") == 0 ? 1 : 2;
我相信如果在执行该行之前地图中不存在word_count["a"]
,则会导致未定义的行为。
这是因为word_count["a"]
将在地图中创建一个条目(如果不存在),这将改变word_count.count("a")
的行为。我们在这两个电话之间也没有必要的排序..