Reputation: 6853
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
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