Почему mySet.erase (it ++) не определяет поведение или нет?

Accordint на этот довольно высоко голословный ответ, канонический способ перебора множества, стирающего некоторые элементы, заключается в следующем:

for (it = mySet.begin(); it != mySet.end(); ) {
if (conditionToDelete(*it)) {
mySet.erase(it++);
}
else {
++it;
}
}

Это, конечно же, результат того, что в C ++ 03 не удаляется итератор. В противном случае можно написать it = mySet.erase(it); Также очевидно, что можно написать

itToDelete = it++;
mySet.erase(itToDelete);

Этот вопрос не о том, как удалять элементы во время итерации. Вопрос в том, почему следующая строка, по-видимому, не привести к неопределенному поведению.

mySet.erase(it++);

Сначала я был уверен, что это должен быть UB, потому что я неправильно думал о постинкременте. Это распространенный (но неправильный) способ думать, что преинкремент произошел ДО остальной части оценки, а постинкремент произошел ПОСЛЕ. Конечно, это неправильно. И постинкремент, и преинкремент имеют побочный эффект увеличения переменной. Разница заключается в значении этих выражений.

Тем не менее, насколько я помню, стандарт C ++ (по крайней мере, C ++ 03) точно не определяет, когда будет иметь место побочный эффект постинкремента. Итак, если у нас нет гарантии, что если аргумент функции, который является выражением postincrement, будет иметь свои побочные эффекты на месте до вход в тело функции, разве это не должно быть UB? Что именно (в соответствии со стандартами), если вообще что-либо, запрещает побочный эффект этого ++, возникающий после того, как итератор был признан недействительным внутри тела функции?

Цитаты из стандарта будут очень приветствоваться.

Ради аргумента давайте также предположим, что итератор множества является встроенным типом, и это на самом деле оператор ++, а не перегруженная оператор-функция.

10

Решение

Это не неопределенное поведение в C ++ 03 потому что есть точка последовательности после того, как все аргументы функции оценены.

Проект стандарта, наиболее близкий к C ++ 03 и общедоступный, N1804, до сих пор нет общедоступной версии проекта стандарта, которую я могу найти, но Статья в Википедии о точках последовательности используемый С ++ 98 а также C ++ 03 как ссылки и фразы соответствуют пунктам ниже N1804.

В разделе 1.9 Выполнение программы параграф 16 говорит (Акцент шахты идет вперед):

При вызове функции (независимо от того, является ли функция встроенной), после оценки всех аргументов функции есть точка последовательности (если есть), который происходит перед выполнением каких-либо выражений или операторов в теле функции. […]

а позже в разделе 5.2.2 Вызов функции параграф 8 говорит:

Порядок оценки аргументов не уточняется. Все побочные эффекты при оценке выражений аргументов вступают в силу до ввода функции. Порядок вычисления выражения postfix и списка выражений аргументов не определен.

11

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]