2.14 C++析构函数

参考: http://www.weixueyuan.net/view/6345.html

总结:
  析构函数就是用于回收创建对象时所消耗的各种资源。
  析构函数的调用顺序与构造函数调用顺序正好是相反的。
  类的构造函数负责对象完成初始化及其它相关操作,而析构函数则用于销毁对象时完成相应的资源释放工作。
 
在创建对象的时候系统会自动调用构造函数,在对象需要被销毁的时候同样系统会自动调用一个函数,这个函数被称之为析构函数。析构函数就是用于回收创建对象时所消耗的各种资源。与构造函数类似,析构函数也是一个成员函数。析构函数与普通成员函数相比,有如下特征:
  • 无返回值
  • 没有参数,不能被重载,因此一个类也只能含有一个析构函数
  • 函数名必须为“~类名”的形式,符号“~”与类名之间可以有空格

在上一节的Array类中,我们没有在类中声明析构函数,在此,我们将其补全如下。

例1:
 
#include<iostream>
using namespace std;

class Array
{
public:
    Array(){length = 0; num = NULL;};
    Array(int * A, int n);
    Array(Array &a);
    void setnum(int value, int index);
    int * getaddress();
    void display();
    int getlength(){return length;}
    ~Array();
private:
    int length;
    int * num;
};

Array::~Array()
{
    if(num != NULL)
        delete[] num;
    cout<<"destructor"<<endl;
}

Array::Array(Array & a)
{
    if(a.num != NULL)
    {
        length = a.length;
        num = new int[length];
        for(int i=0; i<length; i++)
            num[i] = a.num[i];
    }
    else
    {
        length = 0;
        num = 0;
    }  
}

Array::Array(int *A, int n)
{
    num = new int[n];
    length = n;
    for(int i=0; i<n; i++)
        num[i] = A[i];
}

void Array::setnum(int value, int index)
{
    if(index < length)
        num[index] = value;
    else
        cout<<"index out of range!"<<endl;
}

void Array::display()
{
    for(int i=0; i<length; i++)
        cout<<num[i]<<" ";
    cout<<endl;
}

int * Array::getaddress()
{
    return num;
}

int main()
{
    int A[5] = {1,2,3,4,5};
    Array arr1(A, 5);
    arr1.display();
    Array arr2(arr1);
    arr2.display();
    arr2.setnum(8,2);
    arr1.display();
    arr2.display();
    cout<<arr1.getaddress()<<" "<<arr2.getaddress()<<endl;
    return 0;
}
这个例子,现在是一个完整的例子,在这个例子中,我们为其增添了一个析构函数~Array,该函数在main函数退出前被系统自动调用,用于释放num所指向的内存空间。因为有两个对象,因此最终析构函数被调用了两次。

说到析构函数,则其调用顺序则不得不介绍一下了。析构函数与构造函数调用顺序是反转过来的,先调用构造函数的后调用构造函数。我们通过下面的例子来加以说明。

例2:
#include<iostream>
using namespace std;

class test
{
public:
    test(int i){num = i;cout<<num<<" Constructor"<<endl;}
    ~test(){cout<<num<<" Destructor"<<endl;}
private:
    int num;
};

int main()
{
    test t0(0);
    test t1(1);
    test t2(2);
    test t3(3);
    return 0;
}
 
程序运行结果:
0  Constructor
1  Constructor
2  Constructor
3  Constructor
3  Destructor
2  Destructor
1  Destructor
0  Destructor
从这个程序运行不难看出,析构函数的调用顺序与构造函数调用顺序正好是相反的,为了方便记忆,我们可以将之理解为一个栈,先入后出。

类的构造函数负责对象完成初始化及其它相关操作,而析构函数则用于销毁对象时完成相应的资源释放工作。在设计类过程中,我们建议为每个带有成员变量的类设计一个默认构造函数,其它构造函数及析构函数则可以视情况再定。
 
原文地址:https://www.cnblogs.com/yongpan/p/7481318.html