Почему С++ принимает несколько префиксов, но не постфиксов для переменной

Изучая Можете ли вы иметь инкрементор и декрементор для одной и той же переменной в одном и том же операторе в c

Я обнаружил, что у вас может быть несколько префиксных операторов инкремента/декремента для одной переменной, но только один постфикс.

ex:

++--++foo; // valid
foo++--++; // invalid
--foo++;   // invalid

Почему это?


person Ashterothi    schedule 26.07.2012    source источник


Ответы (2)


Это связано с тем, что в C++ (но не в C) результатом ++x является lValue, что означает, что его можно присваивать и, следовательно, можно использовать в цепочке.

Однако результат x++ НЕ является lValue, вместо этого он является prValue, что означает, что его нельзя присвоить и, следовательно, нельзя связать.

person Richard J. Ross III    schedule 26.07.2012

В языке C++ префиксные операторы инкремента/декремента возвращают lvalues, а постфиксные операторы возвращают rvalues. Между тем, все операторы модификации требуют аргументов lvalue. Это означает, что результат инкремента/декремента префикса может быть передан любому другому дополнительному оператору, который требует аргумента lvalue (включая дополнительные инкременты/декременты).

По той же причине в C++ вы можете написать такой код

int i = 0;
int *p = &++i;

который увеличит i и заставит p указывать на i. Унарный & требует операнда lvalue, поэтому он будет работать с результатом префикса ++ (но не с постфиксом).

Выражения с несколькими встроенными инкрементами/декрементами префикса, применяемые к одному и тому же объекту, вызывают неопределенное поведение, но тем не менее они правильно сформированы (то есть "компилируемые").

Выражения типа ++foo-- недействительны, поскольку в C++ постфиксные операторы имеют более высокий приоритет, чем префиксные. Брекеты могут это изменить. Например, (++foo)-- — это правильно сформированное выражение, хотя оно снова приводит к неопределенному поведению.

person AnT    schedule 26.07.2012
comment
Можете ли вы показать документацию, в которой говорится, что результат не определен? Мне кажется, что это должно быть полностью четко определено (оценивается справа налево наружу). - person Richard J. Ross III; 27.07.2012
comment
@RichardJ.RossIII UB, потому что (C++11, 1.9p15) Если побочный эффект на скалярном объекте не является последовательным относительно другого побочного эффекта на тот же скалярный объект или вычисления значения с использованием значения того же скалярного объекта , поведение не определено. - person ouah; 27.07.2012
comment
@Richard J. Ross III: известный абзац 5/4 в спецификации языка C++ (C++98, C++03). Недопустимо (в смысле UB) изменять один и тот же объект дважды, не прерывая sequence point (SP). C++ не определяет порядок оценки встроенных операторов без SP. В С++ без SP нет такой вещи, как оценка слева направо. Любые заказы требуют вмешательства SP. В ++--foo нет точки последовательности, поэтому поведение не определено. C++11 использует другой формальный подход к упорядочению, но основной принцип остается прежним. - person AnT; 27.07.2012