类 和基元的运算符重载行为不同

Operator Overloading behaves differently for classes and primtives

以下代码在编译时 运行 使用 g++ 输出 22

#include <iostream>

int main(){
    int a = 5;
    int c = ++a + ++a + ++a;
    std::cout << c << std::endl;
    return 0;
}

浮点数也计算为相同的值。

而下面的整数包装器 class 输出 24

#include <iostream>

class Int{
public:
    int data;
    
    Int( int value ) : data(value){}
    
    Int& operator++(){
       ++data;
       return *this;
    }
    
    Int operator+( const Int& b ){
        return Int( data + b.data );
    }
    
};

int main(){
    Int a = 5;
    Int c = ++a + ++a + ++a;
    std::cout << c.data << std::endl;
    return 0;
}

我无法理解为什么输出会有所不同。

有人可以详细解释一下这是怎么回事吗?

除此之外,当使用 clang 编译两个代码时,第一个代码输出 21 而第二个代码输出 22.

PS :我知道我不应该使用这样的表达式,但我的问题是为什么 classes 的行为与原始类型不同。他们不应该都解析为相同的语法树并以相同的顺序进行评估吗?即使行为未定义但是对于同一个编译器,它们不应该以相似的方式表现吗

int c = ++a + ++a + ++a;Int c = ++a + ++a + ++a; 都会导致未定义的行为。
你应该避免这样编码。

参见https://en.cppreference.com/w/cpp/language/operator_incdec#Example

并查看 cppreference.com 的 评估顺序 页面的 Undefined behaviour section

Undefined behavior

  1. If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.

    i = ++i + 2;       // undefined behavior until C++11
    i = i++ + 2;       // undefined behavior until C++17
    f(i = -2, i = -2); // undefined behavior until C++17
    f(++i, ++i);       // undefined behavior until C++17, unspecified after C++17
    i = ++i + i++;     // undefined behavior
    
  2. If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.

    cout << i << i++; // undefined behavior until C++17
    a[i] = i++;       // undefined behavior until C++17
    n = ++i + i;      // undefined behavior
    

在这里你可以运行你的代码与不同的编译器
Evaluation order on Visual C++
Evaluation order on Zapcc and GCC

剧透:Visual C++ 对基本类型和 类

的行为方式相同

在 rextester 上,您也可以尝试 Clang 和 GCC,但是我无法在其他链接下方添加这些链接,除非编辑告诉我有一些未格式化的代码(没有)
Evaluation order on Clang
Evaluation order on GCC