feeling_lonely
feeling_lonely

Reputation: 6853

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

I have written this class and driver function:

#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;
}

And here is the output:

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

Why the destructor was called twice after the two assignment operators were called? (i.e., third and sixth lines in the output).

I know these are probably for the temporary variable being used for the addition, but what is the rule or C++ specification for this?

Thanks.

Upvotes: 2

Views: 176

Answers (1)

immortal
immortal

Reputation: 3188

Because indeed the operator+ creates a temporary object which is the result of the operation, and is discarded after the assignment.

Consider your own signature for the operator+: Weight operator+(const double addition) const. This returns, by value, a Weight object instance. This isn't a reference, nor a pointer. It's a de-facto new object that is created to hold the result of m + 1.1, without updating the value of m first (unlike operator+=). This is even more evident from a look in your own code: return Weight(newKg, newG); - a new object is created right here, and it needs to be destroyed.

This temporary value is then assigned into m, and the temporary object is then destroyed as it moves out of scope.

As a side note, what you see here is also an optimization (a standard optimization called "return value optimization") as the explicit behavior for this situation would've been the construction of the temporary value in the return statement inside the stack frame of the operator+, followed by a copy-construction of the value in the stack frame of the calling function main and then the destruction of the object in the operator+ stack frame. Then the value in main would've gone into the assignment operator, and then destroyed too. Your compiler just optimized this code to construct the return value directly on the stack frame of the calling function saving an extra temporary object.

Upvotes: 3

Related Questions