析构函数和释放内存的函数有什么区别?

3

在这段代码中,析构函数和DeAllocate函数有什么区别?

我不理解它们看起来像是一样的。它们做完全相同的事情,为什么你需要一个像DeAllocate这样的函数?析构函数具有自动调用的优点,但DeAllocate没有。

#include <iostream>
using namespace std;

const int SIZE=5;

class ARRAY_CLASS
{
public:
    ARRAY_CLASS();//default constructor
    ~ARRAY_CLASS(); //destructor
    void Add(int); //mutator
    void Print(); //accessor
    int * Get_Address(); //accessor
    void DeAllocate(); //mutator
private:

    int *A;
    int count;
};

ARRAY_CLASS::ARRAY_CLASS()
{
    cout<<"Default constructor has been called\n";
    A = new int[SIZE];
    count = 0;
}


ARRAY_CLASS::~ARRAY_CLASS()
{
    cout<<"The Destructor has been Called!\n";
    delete [ ] A;
    A=0;
    count = 0;
}

void ARRAY_CLASS::Add(int item)
{
    if (count<SIZE)
        A[count++]=item;
    else
        cout<<"Array Full\n";
}
void ARRAY_CLASS::Print()
{
    for(int i=0; i<count; i++)
        cout<<"A[i] = "<<A[i]<<endl;
}

int * ARRAY_CLASS::Get_Address()
{
    return A;
}

void ARRAY_CLASS::DeAllocate()
{
    delete [ ] A;
    A = 0;
    count = 0;
}

int main()
{

    ARRAY_CLASS B;

    B.Add(1);
    B.Add(2);
    B.Add(3);
    B.Add(4);
    B.Add(5);

    B.Print();

    ARRAY_CLASS A = B;

    cout<<"A holds address location = "<<A.Get_Address()
    <<" and B holds address location "<<B.Get_Address()<<endl;

    B.DeAllocate();
    A.Print();

    return 0;
}

2
析构函数的优势在于自动调用,但DeAllocate没有这个功能。就是这样,没有比这更好的了。RAII依赖于此。而且大多数语言都有相同的概念,即使是托管语言(例如C#中的IDisposable与using结合使用)。这使我们的日常生活变得更加美好。 - Frédéric Hamidi
离题:强烈建议使用A = nullptr;而不是A = 0;。对于普通读者来说,第一个的意图更加明显。 - user4581301
1
DeAllocate() 方法在这里可能根本不应该存在。它会使对象处于无效状态。应该只有一个析构函数。 - user207421
2个回答

4

确实可以重新编写析构函数:

ARRAY_CLASS::~ARRAY_CLASS()
{
    cout<<"The Destructor has been Called!\n";
    DeAllocate();
}

区别在于:
  • 析构函数会在销毁对象时被调用(对于局部对象,当离开创建对象的作用域时自动调用;对于堆上的对象,当对象被删除时调用)。对象被销毁后,该对象不再存在。

  • 当调用DeAllocate();时,数组的内存被释放,对象的状态发生改变,但是它的所有成员和ARRAY_CLASS对象本身仍然存在。


3
析构函数会在对象本身被移除时发生。
在您发布的示例中,您可以将该函数重命名为其他名称,例如 void ARRAY_CLASS::ClearArray() 而不是 void ARRAY_CLASS::DeAllocate()。您所做的只是释放 A 使用的内存,而不是销毁整个对象。

你不需要调用析构函数。当你删除一个对象或它超出作用域时,析构函数会自动被调用。 - rebnat
1
在你发布的示例中,如果数组是你唯一担心清除的数据,你可以让析构函数调用deallocate函数。 - rebnat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接