После ответа на этот вопрос возник долгая дискуссия о том, является ли рассматриваемый код неопределенным поведением или нет. Вот код:
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]++;
в мире будут неправильно сформированы.
Полезная ссылка: Неопределенное поведение и точки последовательности