Я обнаружил, что у вас может быть несколько префиксных операторов инкремента/декремента для одной переменной, но только один постфикс.
ex:
++--++foo; // valid
foo++--++; // invalid
--foo++; // invalid
Почему это?
Я обнаружил, что у вас может быть несколько префиксных операторов инкремента/декремента для одной переменной, но только один постфикс.
ex:
++--++foo; // valid
foo++--++; // invalid
--foo++; // invalid
Почему это?
Это связано с тем, что в C++ (но не в C) результатом ++x
является lValue, что означает, что его можно присваивать и, следовательно, можно использовать в цепочке.
Однако результат x++
НЕ является lValue, вместо этого он является prValue, что означает, что его нельзя присвоить и, следовательно, нельзя связать.
В языке C++ префиксные операторы инкремента/декремента возвращают lvalues, а постфиксные операторы возвращают rvalues. Между тем, все операторы модификации требуют аргументов lvalue. Это означает, что результат инкремента/декремента префикса может быть передан любому другому дополнительному оператору, который требует аргумента lvalue (включая дополнительные инкременты/декременты).
По той же причине в C++ вы можете написать такой код
int i = 0;
int *p = &++i;
который увеличит i
и заставит p
указывать на i
. Унарный &
требует операнда lvalue, поэтому он будет работать с результатом префикса ++
(но не с постфиксом).
Выражения с несколькими встроенными инкрементами/декрементами префикса, применяемые к одному и тому же объекту, вызывают неопределенное поведение, но тем не менее они правильно сформированы (то есть "компилируемые").
Выражения типа ++foo--
недействительны, поскольку в C++ постфиксные операторы имеют более высокий приоритет, чем префиксные. Брекеты могут это изменить. Например, (++foo)--
— это правильно сформированное выражение, хотя оно снова приводит к неопределенному поведению.
++--foo
нет точки последовательности, поэтому поведение не определено. C++11 использует другой формальный подход к упорядочению, но основной принцип остается прежним.
- person AnT; 27.07.2012