为什么对象的析构函数在赋值操作完成后被调用
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 值,从而节省了一个额外的临时对象。
我写了这个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 值,从而节省了一个额外的临时对象。