C++重载赋值运算符的一点疑问
本帖最后由 yuanming1027 于 2022-9-14 13:45 编辑class Na {
public:
int *age;
Na(int a) {
age = new int(a);
}
Na& operator=(Na dy) {
if (age != NULL) {
delete age;
age = NULL;
};
age = new int(*dy.age);
return *this;
}
~Na() {
if (age != NULL) {
delete age;
age = NULL;
}
}
};
int main() {
Na a1(10);
Na a2(20);
a1 = a2;
cout << *a1.age << endl;
cout << *a2.age << endl;
system("pause");
return 0;
}
此代码是重载赋值运算符,用深拷贝解决浅拷贝带来的重复释放堆区数据。
如果重载函数的参数带上&,则输出正常为20.
如果不带&,则a2.age是负数,a1.age正常为20.
为什么a2.age是负数? 没听懂你到底要问什么 编程追风梦 发表于 2022-9-14 14:02
没听懂你到底要问什么
为什么重载赋值运算符的参数不带&,a2.age输出的是负数 本帖最后由 jhq999 于 2022-9-14 14:38 编辑
把引用&去掉也都是20,难道与编译器有关系? 把您的析构函数做了一点调整(加了一行辅助输出),您看看修改后的两种情况下的运行输出有什么区别,应该能给您一些启发。
~Na() {
if (age != NULL) {
cout << "non-trivial destructor invocation\n";
delete age;
age = NULL;
}
} dolly_yos2 发表于 2022-9-14 16:14
把您的析构函数做了一点调整(加了一行辅助输出),您看看修改后的两种情况下的运行输出有什么区别,应该能 ...
666 jhq999 发表于 2022-9-14 14:37
把引用&去掉也都是20,难道与编译器有关系?
不是返回值类型的&,是参数里面的&。这个疑问已经解决了 dolly_yos2 发表于 2022-9-14 16:14
把您的析构函数做了一点调整(加了一行辅助输出),您看看修改后的两种情况下的运行输出有什么区别,应该能 ...
他为什么会调用析构函数呢? yuanming1027 发表于 2022-9-14 19:58
他为什么会调用析构函数呢?
我的理解是这样的,当不加 & 的时候,赋值运算符的右操作数被按值传递进入重载的赋值函数,即复制为一个新的 Na 类型实例,这个新的实例中指针的值与右操作数一致,因此赋值可以正确的更新左操作数的值,但这个复制得到的新实例的生命周期在重载运算符方法调用完毕前结束,因此将会调用这个临时实例的析构函数导致右操作数内的指针被释放。
这一过程应该可以通过下面的代码进行直观观察
#include <iostream>
using namespace std;
class Na {
public:
int *age;
Na(int a) {
age = new int(a);
}
Na& operator=(Na dy) {
cout << "dy: " << addressof(dy) << endl;
if (age != NULL) {
delete age;
age = NULL;
};
age = new int(*dy.age);
return *this;
}
~Na() {
if (age != NULL) {
cout << "non-trivial destructor invocation for " << this << endl;
delete age;
age = NULL;
}
}
};
int main() {
Na a1(10);
Na a2(20);
cout << "a1: " << addressof(a1) << endl;
cout << "a2: " << addressof(a2) << endl;
a1 = a2;
cout << *a1.age << endl;
cout << *a2.age << endl;
return 0;
}
页:
[1]