5

在设计一个动态分配内存的类时,我遇到了以下关于内存分配的问题。我希望你们中的一些人能够指出我应该如何以更好的方式设计我的课程的正确方向。我的类动态分配内存,因此也在其析构函数中删除它。

为了说明问题,请考虑以下愚蠢的类声明:

class testClass{
    int* data;
public:
    testClass(){
        data = new int;
        *data = 5;
    }
    ~testClass(){
        delete data;
    }
};

到现在为止还挺好。现在假设我在 main 中创建了这些对象之一

int main(){
    testClass myObject;
    return 0;
}

当然仍然没有问题。但是,假设我现在编写了一个函数,该函数将 testClass 对象作为输入并从 main 中调用它。

void doNoting(testClass copyOfMyObject){
    //do nothing
}
int main(){
    testClass myObject;
    doNothing(myObject);
    return 0;
}

这一次,该函数创建了一个局部变量 copyOfMyObject,它只是 myObject 的一个副本。然后,当到达该函数的末尾时,该本地对象会自动调用其析构函数,该析构函数会删除其数据指针指向的内存。但是,由于这是 myObject 的数据指针所指向的同一块内存,因此 myObject 在此过程中无意中删除了它的内存。我的问题是:设计课程的更好方法是什么?

4

3 回答 3

7

当您调用 时doNothing(),它会复制您的testClass对象,因为它是按值传递的。不幸的是,当这个副本被销毁时,它会调用析构函数,它会删除data原始实例使用的相同内容testClass

您想了解“复制构造函数”和“按引用传递”。也就是说,您应该为您的类定义一个复制构造函数,以便在复制一个实例时,它会为其data成员分配自己的内存。此外,您可以传递指针或对 的引用,而不是按值传递doNothing(),这样就不会进行复制。

于 2013-03-05T18:39:02.943 回答
2

您应该创建一个复制构造函数,即以下形式的构造函数:

testClass::testClass(const testClass &o)
{ 
    // appropriate initialization here
}

在您的情况下,“适当的初始化”可能意味着分配一个新的内存块并将内存从旧块复制到新块中。或者它可能意味着进行引用计数。管他呢。

您还应该在 StackOverflow 上阅读更多关于三法则的信息!

于 2013-03-05T18:40:27.883 回答
0

这是权威的指导方针:具有 {destructor, assignment operator, copy constructor} 的类通常需要全部 3

您需要一个复制构造函数,它将为您的数据分配一个新的 int,然后将其破坏,但不影响原始数据。

或者,您可以创建一个空白的私有复制构造函数,从而有效地禁用它,强制您的用户通过引用或其他非复制方式进行操作。

于 2013-03-05T18:41:46.497 回答