С++: условная вставка ключа и значения в std:: map

Если я это сделаю:

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. Почему??

Ответ 1

Официально, обе стороны задания могут быть оценены первыми. Это решение, чтобы решить, какой. Если word_count не содержит "a", один вставлен и возвращается ссылка lvalue. Если 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, демонстрируют хорошо определенное поведение даже в том случае, если элемент вставлен и затем назначен.

Ниже дается обсуждение и обсуждение того, верны они или нет. Я уже сделал это более официальным.

Ответ 2

Глядя на эту строку:

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

I верьте, что если word_count["a"] не существует на карте до того, как эта строка будет выполнена, вы вызываете поведение undefined.

Это потому, что word_count["a"] создаст запись на карте, если она не существует, и это изменит поведение word_count.count("a"). У нас также нет требуемой последовательности между этими двумя вызовами.