Dev-C++和Code::Blocks中的析构函数出错

Destructors messing up in Dev-C++ and Code::Blocks

本文关键字:析构函数 出错 Blocks Code Dev-C++      更新时间:2023-10-16
#include <iostream>
using namespace std;
class Exem {
int *a;
public:
Exem() { a = new int; *a = 0; };
Exem (int x) { a = new int; *a = x; };
~Exem () { delete a; };
int f (void);
Exem operator+ (Exem);
};
int Exem::f (void) {
return *a * 2;
}
Exem Exem::operator+ (Exem nimda) {
Exem aux;
*aux.a = *a + *nimda.a;
return aux;
}
int main() {
Exem adabo(1);
Exem inakos(2);
adabo = adabo + inakos;
cout << adabo.f();
cin.get();
}

这是我的代码,一个用来展示这个问题的示例类。理论上,main()的输出是"6",但实际显示的都是荒谬的数字。

这显然与类的析构函数有关,据我所知,析构函数在运算符+函数结束时调用得太早——aux在实际传递之前就丢失了。我得出这样的结论是因为~Exem()在注释时允许程序按预期执行。

我猜这与这两个编译器有关,因为当我试图在Embarcadero RAD Studio中编译完全相同的代码时,它会起作用。

您需要为Exem显式定义一个复制构造函数和赋值运算符,因为您有一个动态分配的成员变量。

如果没有为类显式定义复制构造函数和赋值运算符,编译器将生成这些构造函数和赋值操作符的默认版本,这些版本不适合具有动态分配成员的类。默认生成的版本不合适的原因是它们执行成员的浅层复制。在Exem的情况下,当复制其实例时,Exem的多个实例指向名为a的同一动态分配的int成员。当其中一个实例被破坏时,adeleted,并留下一个悬空指针和未定义的行为的另一个实例。

请参阅三条规则。

Exem的一个简单修复是将aint*更改为int。默认的复制构造函数、赋值运算符和析构函数是正确的。


请注意,Exem::operator+()应采用const Exem&参数,因为它不会更改其参数。