在回答这个问题后,有一场长时间的讨论,关于问题中的代码是否存在未定义行为。下面是代码:
std::map<string, size_t> word_count;
word_count["a"] = word_count.count("a") == 0 ? 1 : 2;
首先,很明显这至少是未指定的。根据评估的顺序不同,结果也会有所不同。在我的回答中,我详细解释了四种情况,包括哪一边被先评估以及元素是否存在于此之前。
还有一个简短的表格:
(x = 0) = (x == 0) ? 1 : 2; //started as
(x = 0) = (y == "a") ? 1 : 2; //changed to
我认为更像这样:
(x = 0, x) = (x == 0) ? 1 : 2; //comma sequences x, like [] should
最终,我找到了一个似乎适合我的示例:
i = (++i,i++,i); //well-defined per SO:Undefined Behaviour and Sequence Points
回到原始代码,我将其分解为相关的函数调用,以便更容易跟踪:
operator=(word_count.operator[]("a"), word_count.count("a") == 0 ? 1 : 2);
^ inserts element^ ^reads same element
|
assigns to element
如果
word_count["a"]
不存在,则认为它将在没有顺序的情况下被分配两次。个人认为如果我认为的两件事情是真的,那么这种情况不会发生:
在评估选择的一侧之前,必须评估整个一侧。
例如word_count["a"] = 1的结构具有良好定义的行为,即使在插入元素后再进行赋值的情况下也是如此。
myMap[i]++;
都是不合法的。有用的链接:未定义的行为和序列点