为什么对象的析构函数在赋值操作完成后被调用

Why object's destructor was called after assignment operation is done

我写了这个class和驱动函数:

#include <cstdlib>
#include <iostream>

using namespace std;

class Weight {
    int grams;
    int kilograms;

public:

    Weight(int kg, int g) : kilograms(kg), grams(g) {
    }

    ~Weight() {
        cout << "Destructor " << this->kilograms << " " << this->grams << "\n";
    }

    friend Weight operator+(const Weight& a, const Weight& b);

    Weight operator+(const Weight& w) const {
        cout << "member operator+\n";
        int newKg = this->kilograms + w.kilograms;
        int newG = this->grams + w.grams;
        if (newG >= 1000) {
            newG -= 1000;
            newKg += 1;
        }
        return Weight(newKg, newG);
    }

    Weight operator+(const int addition) const {
        cout << "operator+int" << endl;
        int newKg = this->kilograms;
        int newG = this->grams + addition;
        if (newG >= 1000) {
            newG -= 1000;
            newKg += 1;
        }
        return Weight(newKg, newG);
    }

    Weight operator+(const double addition) const {
        cout << "operator+double" << endl;
        int newKg = this->kilograms + ((int) addition);
        int newG = this->grams + (1000 * (addition - ((int) addition)));
        if (newG >= 1000) {
            newG -= 1000;
            newKg += 1;
        }
        return Weight(newKg, newG);
    }

    Weight& operator=(const Weight & w) {
        cout << "Assignment operator\n";
        this->grams = w.grams;
        this->kilograms = w.kilograms;
        return *this;
    }

    void print() {
        cout << "Weight is: " << this->kilograms << " Kilograms and " << this->grams <<
                " Grams\n";
    }

};

Weight operator+(const Weight& a, const Weight& b) {

    cout << "Friend plus\n";
    int newKg = a.kilograms + b.kilograms;
    int newG = a.grams + b.grams;
    if (newG >= 1000) {
        newG -= 1000;
        newKg += 1;
    }
    return Weight(newKg, newG);
}

int main(int argc, char** argv) {
    Weight m(90, 900);
    m = m + 1.1;
    m = m + m;
    m.print();
    return 0;
}

这是输出:

operator+double
Assignment operator
Destructor 92 0
Friend plus
Assignment operator
Destructor 184 0
Weight is: 184 Kilograms and 0 Grams
Destructor 184 0

为什么调用了两次赋值运算符后又调用了两次析构函数? (即输出中的第三行和第六行)。

我知道这些可能是用于加法的临时变量,但是这方面的规则或 C++ 规范是什么?

谢谢。

因为确实 operator+ 创建了一个临时对象,它是操作的结果,并在赋值后被丢弃。

考虑一下您自己对 operator+ 的签名:Weight operator+(const double addition) const。这个 returns,按值,一个 Weight 对象实例。这不是参考,也不是指针。这是一个事实上的新对象,创建它是为了保存 m + 1.1 的结果,而不是首先更新 m 的值(与 operator+= 不同)。从您自己的代码中可以看出这一点:return Weight(newKg, newG); - 此处创建了一个新对象,需要将其销毁。

然后将此临时值分配给 m,然后临时对象在移出范围时被销毁。

附带说明一下,您在这里看到的也是一种优化(称为 "return value optimization" 的标准优化),因为这种情况下的显式行为是在 [= operator+ 的堆栈帧中的 19=] 语句,然后是调用函数 main 的堆栈帧中值的复制构造,然后是 [=10 中的对象的销毁=] 栈帧。然后 main 中的值将进入赋值运算符,然后也被销毁。您的编译器刚刚优化了这段代码,直接在调用函数的堆栈帧上构造了 return 值,从而节省了一个额外的临时对象。