析构函数搞乱了Dev-C ++和Code :: Blocks

时间:2012-10-12 19:40:17

标签: c++ destructor codeblocks dev-c++

#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会丢失。我得出了这样的结论,因为~exm()在被注释时允许程序按预期执行。

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

1 个答案:

答案 0 :(得分:2)

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

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

请参阅rule of three

Exem的简单修正方法是aint*更改为int。默认的复制构造函数,赋值运算符和析构函数都是正确的。


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