Стандарт C ++ 11 (5.17, expr.ass) утверждает, что
Во всех случаях присваивание последовательности после вычисления значения
правого и левого операндов, и до вычисления значения
выражение присваивания. По отношению к
неопределенно-последовательный вызов функции, операция соединения
задание является одной оценкой
Значит ли это, что выражение:
int a = 1, b = 10;
int c = (a+=1) + (b+=1);
if ( c == 10+1+1+1 ) {
printf("this is guaranteed");
} else {
printf("not guaranteed");
}
всегда буду оценивать c==23
?
Это всегда гарантировано, и последовательность перед правилами
(или правила точки последовательности в пре-C ++ 11) не нужно
определить это. В C ++ каждое (под) выражение имеет два важных
эффекты в сгенерированном коде: оно имеет значение (если оно не
тип void
), и это может иметь побочные эффекты. Последовательный
Правила точки до / последовательности влияют, когда побочные эффекты
гарантированно состоялось; они не влияют на стоимость
подвыражений. В вашем случае, например, значение
из (a += 1)
это значение a
будет после назначения,
независимо от того, когда фактическое назначение имеет место.
В C ++ 11 актуальная модификация a
гарантированно взять
место до модификации c
; в до C ++ 11 не было
гарантия относительно заказа. В этом случае, однако, есть
Соответствующая программа никак не могла увидеть эту разницу, поэтому
не имеет значения (Это будет иметь значение в таких случаях, как c = (c += 1)
,
что было бы неопределенным поведением в пре-C ++ 11.)
Выражение
int c = (a+=1) + (b+=1);
(редактировать: добавлены недостающие скобки, я думаю, это то, что вы хотели)
имеет следующие подвыражения
(1) a+=1
(2) b+=1
(3) (1)+(2)
(4) c = (3)
Порядок, в котором оцениваются (1) и (2), не указан, компилятор может выбирать любой порядок, который ему нравится.
Оба (1) и (2) должны быть оценены до Компилятор может оценить (3).
(3) должны быть оценены до Компилятор может оценить (4).
Теперь, когда порядок вычисления (1) и (2) не имеет значения, общий результат хорошо определен, ваш код всегда будет давать 13
и выведите «теперь это стандарт». Обратите внимание, что так было всегда, это не ново для C ++ 11.
В вашем примере компилятор выдаст ошибку, потому что приоритет оператора сложения выше, чем приоритет оператора присваивания. Таким образом, сначала будет вычислено 1 + b, а затем будет попытка присвоить 1 выражению (1 + b), но (1 + b) не является lvalue.