2
#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”,但实际显示的只是无意义的数字。

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

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

4

1 回答 1

2

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

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

三法则

A simple fix for Exem would be change a from an int* to an int. The default copy constructor, assignment operator and destructor would be correct.


Note that Exem::operator+() should take a const Exem& parameter as it does not change its argument.

于 2012-10-12T19:47:55.027 回答