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

时间:2017-11-23 07:31:48

标签: c++ class oop c++11 destructor

我写过这个类和驱动函数:

#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 ++规范是什么?

感谢。

1 个答案:

答案 0 :(得分:3)

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

考虑operator+Weight operator+(const double addition) const的自己签名。这将按值返回Weight对象实例。这不是引用,也不是指针。它是一个事实上的新对象,用于保存m + 1.1的结果,而不首先更新m的值(与operator+=不同)。从你自己的代码中看,这一点更加明显:return Weight(newKg, newG); - 在这里创建了一个新对象,它需要被销毁。

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

作为旁注,你在这里看到的也是一种优化(标准优化称为&#34;返回值优化&#34;)因为这种情况的明确行为将是临时的构建return的堆栈帧内的operator+语句中的值,然后是调用函数main的堆栈帧中的值的复制构造,然后是对象的销毁在operator+堆栈框架中。然后main中的值将进入赋值运算符,然后也被销毁。您的编译器只是优化了此代码,以直接在调用函数的堆栈帧上构造返回值,从而节省了额外的临时对象。