后自增要求操作数应该是可修改的左值但后自增的结果是prvalue http://en.cppreference.com/w/cpp/language/value_category(“纯”右值)这是不可修改的,下图显示了正在发生的事情:
i = (j++)++ ;
^ ^
| |
| Result is a prvalue, not a valid operand for subsequent post-increment
Modifiable lvalue
了解 C 和 C++ 中的左值和右值 http://eli.thegreenplace.net/2011/12/15/understanding-lvalues-and-rvalues-in-c-and-c/如果您需要了解两者之间的区别,这是一个很好的起点lvalues and rvalues。
来自C++ 标准草案 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf部分5.2.6
递增和递减 [expr.post.incr]段落1 says(重点是我在随后的引用中):
后缀++表达式的值是其操作数的值。 [注:获取到的值是原始值的副本——尾注]操作数应是可修改的左值. [..] 结果是纯右值。
Update
我针对未定义的行为重新设计了我的语言,因为这里存在差异C++03 and C++11.
尽管第一个表达式显示:
i = ++++j ;
不会产生错误,但如果这是C++03 and j
是一个基本类型,这是未定义的行为 http://en.wikipedia.org/wiki/Undefined_behavior因为在一个时间内多次修改它的值序列点 http://en.wikipedia.org/wiki/Sequence_point未定义。中的相关部分较旧的标准草案 http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2005/n1804.pdf将是部分5
表达式段落4其中说:
[...]在上一个和下一个序列点之间,标量对象的存储值最多修改一次通过表达式的求值。此外,应仅访问先前值以确定要存储的值。对于完整表达式的子表达式的每个允许的排序,应满足本段的要求;否则行为是未定义的。
它给出了一些例子,其中之一如下:
i = ++i + 1; // the behavior is undefined
In C++11相对于同一标量对象上的另一个副作用,语言对同一标量对象上的副作用的更改是无序的,则行为是未定义的。所以这实际上是很好定义的C++11,在部分1.9
程序执行段落15 says:
除非另有说明,否则各个运算符的操作数和各个表达式的子表达式的求值都是无序的。 [...]如果标量对象上的副作用相对于同一标量对象上的另一个副作用或使用同一标量对象的值的值计算是无序的,则该行为是未定义的。
以这种方式使用后增量和预增量不会导致可读(可维护的)在两种情况下都使用代码j +=2
在赋值语句之前或之后就足够了