Давайте просто возьмем для примера конкретный составной оператор присваивания ^=
, Эта страница говорит, что изменение левого операнда, возможно, не было сделано после оценки ^=
и, таким образом, делая код a ^= b ^= a ^= b
неопределенное поведение. Но, похоже, это не так. Стандарт говорит в 5.17 [expr.ass], что
Во всех случаях присваивание последовательности после вычисления значения
правого и левого операндов, и до вычисления значения
выражение присваивания.
В этом утверждении есть два ключевых момента. 1) Чем занимается предмет назначение относится к? На мой взгляд, это относится только к модификации левого операнда. 2) Что делает вычисление значения выражения присваивания относится к? cppreference говорит, что это относится к возвращению ссылки на модифицированный объект (акцент мой).
В заключение, левый операнд уже должен был быть изменен после оценки ^=
Это противоречит тому, что думают (большинство) люди. Я что-то здесь упускаю?
Вы ссылаетесь на вопрос C. Однако это не имеет значения, поскольку C и C ++ — это разные языки.
Кроме того, точки последовательности больше не существуют с C11 и C ++ 11; вместо отношений последовательность перед, unsequenced, а также неопределенно последовательность существовать.
В этой цитате:
a
,2 + 2
является 4
и вычисление значения — это процесс определения того, что 4
была ценность).Здесь есть два вычисления значения: a ^ b
, а также a =
(этот результат).
В цитируемом тексте, для a = a ^ b
все должно происходить в следующем порядке:
Получить значения из a
а также b
(в любом порядке) и определите область памяти, в которой нужно сохранить результат (вычисление значения правого и левого операнда соответственно)
Сохранить результат в a
(назначение). Включает в себя вычисление значения a ^ b
, который не упоминается в цитате, но ясно, что результат должен быть рассчитан до его сохранения
Выполните вычисление значения выражения присваивания. Это означает возвращение значения, хранящегося в a
готов к использованию окружающего выражения (вычисление значения).
Вы правы в том, что 2 и 3 кажутся «задом наперед» по сравнению с порядком, который вы могли бы делать на бумаге. Но помните, что в целом, y
отличается от значения x = y
, Значение выражения присваивания совпадает со значением, хранящимся в x
, (Пример: int x; double y = (x = 6.5);
— затем y
является 6
не 6.5
). Таким образом, мы можем сделать это, сохранив результат в a
а затем предлагая a
в результате.
а ^ = б ^ = а ^ = б
Есть 3 левых операнда без четкого правила, которые должны быть использованы в первую очередь в вычислительных