Ответ 1
Да, это покрывается стандартом, и это неуказанное поведение. Этот конкретный случай рассматривается в недавнем предложении стандартов на С++: N4228: уточнение порядка оценки выражений для Idiomatic С++, целью которого является уточнение порядка правил оценки чтобы он был хорошо определен для определенных случаев.
Он описывает эту проблему следующим образом:
Порядок оценки выражений является повторяющейся темой обсуждения в С++ сообщества. В двух словах, учитывая выражение, такое как f (a, b, c), порядок, в котором оцениваются подвыражения f, a, b, c, не указывается стандартом. Если какие-либо два из этих подвыражений могут изменить один и тот же объект без промежуточных точек последовательности, то поведение программы будет undefined. Например, выражение f (i ++, i), где я является целочисленная переменная приводит к поведению undefined, как и v [i] = я ++. Даже если поведение не undefined, результат оценки выражения все равно может быть угадан. Рассматривать следующий фрагмент программы:
#include <map> int main() { std::map<int, int> m; m[0] = m.size(); // #1 }
Что должен выглядеть объект карты m после оценки выражение помечено # 1? {{0, 0}} или {{0, 1}}?
Мы знаем, что если не указано, оценки подвыражений не подвержены последовательности, это из черновик С++ 11 1.9
Выполнение программы, которая гласит:
За исключением тех случаев, когда отмечено, оценки операндов отдельных операторов и подвыражений отдельных выражений не подвержены. [...]
и весь раздел 5.17
Операторы присваивания и составного присваивания [expr.ass] говорят:
[...] Во всех случаях назначение упорядочивается после значения вычисление правого и левого операндов и перед вычислением значения выражения присваивания. [...]
Таким образом, этот раздел не ограничивает порядок оценки, но мы знаем, что это не поведение undefined, так как оба operator []
и size()
являются вызовами функций, а раздел 1.9
сообщает нам (выделение мое):
[...] При вызове функции (независимо от того, является ли функция встроенной), каждое вычисление значения и побочный эффект, связанное с любым выражением аргумента, или с выражением postfix, обозначающим вызываемую функцию, является секвенированы перед выполнением каждого выражения или выражения в теле вызываемой функции. [Примечание: значение вычисления и побочные эффекты, связанные с разными выражениями аргументов, не имеют никакого значения. -end note] Каждая оценка в вызывающей функции (включая другие вызовы функций), которая иначе не является секвенированные до или после выполнения тела вызываемой функции, неопределенно секвенированы с относительно выполнения вызываемой функции.9 [...]
Обратите внимание, что я рассмотрю второй интересный пример из предложения N4228
в этом здесь.
Обновить
Кажется, что пересмотренная версия N4228
была принята рабочей группой Evolution на последней встрече WG21, но документ (P0145R0) пока недоступно. Таким образом, это возможно больше не будет неопределенным в С++ 17.