C++ 递增后运算符和递增前运算符的优先级

C++ 递增后运算符和递增前运算符的优先级,c++,operators,C++,Operators,代码如下: #include <iostream> class Int { public: Int() : x(0) {} Int(int x_) : x(x_) {} Int& operator=(const Int& b) { std::cout << "= from " << x << " = " << b.x << std::endl; x =

代码如下:

#include <iostream>

class Int {
public:
    Int() : x(0) {}
    Int(int x_) : x(x_) {}
    Int& operator=(const Int& b) {
        std::cout << "= from " << x << " = " << b.x << std::endl;
        x = b.x;
    }
    Int& operator+=(const Int& b) {
        std::cout << "+= from " << x << " + " << b.x << std::endl;
        x += b.x;
        return *this;
    }
    Int& operator++() {
        std::cout << "++ prefix " << x << std::endl;
        ++x;
        return *this;
    }
    Int operator++(int) {
        std::cout << "++ postfix " << x << std::endl;
        Int result(*this);
        ++x;
        return result;
    }
private:
    int x;

};

Int operator+(const Int& a, const Int& b) {
    std::cout << "operator+" << std::endl;
    Int result(a);
    result += b;
    return result;
}

int main() {
    Int a(2), b(3), c(4), d;
    d = ++a + b++ + ++c;
    return 0;
}
虽然后缀运算符的优先级高于前缀运算符,但为什么后缀运算符不在前缀运算符(++前缀4)之前执行


这是由g++编译的。

不同操作数的求值顺序未指定,这意味着编译器可以随意重新排序
++a
b++
++c
子表达式的求值顺序。在该示例中,运算符的优先级实际上没有任何影响


如果您尝试编写
++i++
(其中
i
int
),它将被分组为
++(i++)
,并且它将无法编译,因为子表达式
i++
是右值,前缀增量需要左值。如果优先级颠倒,则该表达式将编译(并导致未定义的行为)

后缀
++
在表达式
+++a+b+++++c
中具有最高的优先级,但
++
具有最低的优先级,并且是左关联的。这个表达式可以等价地写为
(++a)+(b++++++++(++c)
(每个
++
都是不同子表达式的一部分),这解释了为什么首先计算
++a
。考虑遍历/评估相应的解析树,评估结果的顺序变得明显:

           E
         / | \
        /  |  E
       /   |  | \
      E    +  ++  c
    / | \
   /  |  \
  E   +   E
 / \     / \
++  a   b  ++

它不会对
++a
b++
++c
进行重新排序,但它们的评估是独立的。我已经编译了这样的语句++a++(++b)++,没有错误。对于示例中的类,它可以工作,但对于像int这样的类型,它不能工作:error:levalue需要作为增量operand@Benoit:是的,我是从这个句子开始的,但后来忘了把最重要的地方说清楚。@scdmb:是的,我应该说得更准确些。在这种情况下,因为它是一种用户定义的类型,提供了表达式编译和良好定义的操作,但在基本类型为
int
的情况下,注释为:
int i=0++i++编译失败,
int i=0;(++i)+是未定义的行为。对于用户定义的类型,
++i++
将导致调用后增量,然后调用前增量,证明运算符的优先级,对吗?@scdmb:对于
int i
,它是未定义的行为,因为(用C++03的说法)整数在表达式中修改两次,没有任何中间序列点。我必须回顾一下C++11标准,因为整个序列点术语都不存在了。。。至于一个可能出错的例子。。。在这个特定的例子中,很难找到可能导致不同结果的操作顺序,但标准允许这样做。
           E
         / | \
        /  |  E
       /   |  | \
      E    +  ++  c
    / | \
   /  |  \
  E   +   E
 / \     / \
++  a   b  ++