析构函数为成员函数的一种,名字与类名相同,在前面加‘~’没有参数和返回值在C++中“~”是位取反运算符。
一个类最多只能有一个析构函数。析构函数不返回任何值,没有函数类型,也没有函数参数,因此它不能被重载。
构造函数可能有多个,但析构函数只能有一个,就像人来到人世间,可能出生的环境家庭不同(重载构造函数),但最终都会死亡(析构函数)。
class C { public: ~C ( ) { } ~C (int i) { } // error C2524: “C”: 析构函数 必须有“void”参数列表 // warning C4523: “C”: 指定了多个析构函数 };
析构函数对象消亡时即自动被调用。可以定义析构函数来在对象消亡前做善后工作,比如释放分配的空间等。
如果定义类时没写析构函数,则编译器生成缺省析构函数。缺省析构函数什么也不做。如果定义了析构函数,则编译器不生成缺省析构函数。
析构函数的作用并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作。
例:
class A { private : char * p; public: A ( ) { p = new char[10]; } ~ A ( ) { delete [] p; } };
若A类没写析构函数,则在生成A对象后,new出来的内存空间未清除,可能造成内存泄露。
在创建一类的对象数组时,对于每一个数组元素,都会执行缺省的构造函数。同样,对象数组生命期结束时,对象数组的每个元素的析构函数都会被调用。
#include<iostream> using namespace std; unsigned count = 0; class A { public: A ( ) { i = ++count; cout << "Creating A " << i <<endl; } ~A ( ) { cout << "A Destructor called " << i <<endl; } private : int i; }; int main( ) { A ar[3]; // 对象数组 return 0; }
程序执行结果为:
Creating A 1
Creating A 2
Creating A 3
A Destructor called 3
A Destructor called 2
A Destructor called 1
类似于栈的后进先出
如果出现以下几种情况,程序就会执行析构函数:
(1)如果在一个函数中定义了一个对象(它是自动局部对象),当这个函数被调用结束时,对象应该释放,在对象释放前自动执行析构函数。
(2)static局部对象在函数调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用static局部对象的析构函数。
(3)如果定义了一个全局对象,则在程序的流程离开其作用域时(如main函数结束或调用exit函数) 时,调用该全局对象的析构函数。
(4)如果用new运算符动态地建立了一个对象,当用delete运算符释放该对象时,先调用该对象的析构函数。
(5)调用复制构造函数后。
例:
例4.35 #include <iostream> using namespace std; class CMyclass { public: ~CMyclass( ) { cout << "destructor" << endl; } }; CMyclass obj; CMyclass fun(CMyclass sobj ) { return sobj; //函数调用返回时生成临时对象返回 } void main( ) { obj = fun(obj); //函数调用的返回值(临时对象)被用过后,该临时对象析构函数被调用 }
程序执行结果为:
destructor // 形参和实参结合,会调用复制构造函数,临时对象析构
destructor // return sobj函数调用返回,会调用复制构造函数,临时对象析构
destructor // obj对象析构
总之,在临时对象生成的时候会有构造函数被调用,临时对象消亡导致析构函数调用。
构造函数用于对对象中的变量赋初值,析构函数用于释放所定义的对象的所有内存空间。构造函数和析构函数都不需要用户调用的,构造函数在定义对象时自动调用,析构函数当对象的生存期结束的时候会自动的调用。一般来说,析构函数的调用顺序与构造函数相反。但对象存储类型可以改变析构函数的调用顺序。
全局范围中定义的对象的构造函数在文件中的任何其他函数(包括main)执行之前调用(但不同文件之间全局对象构造函数的执行顺序是不确定的)。全局变量是需要在进入main()函数前即初始化的,所以在一个程序中一个全局变量的构造函数应该是第一个被调用的,比main()函数都要早。同时全局对象又必须在main()函数返回后才被销毁,当main终止或调用exit函数时调用相应的析构函数,所以它的析构函数是最后才被调用。
当程序执行到对象定义时,调用自动局部对象的构造函数。该对象的析构函数在对象离开范围时调用(即离开定义对象的块时)。自动对象的构造函数与析构函数在每次对象进人和离开范围时调用。
static局部对象的构造函数只在程序执行首次到达对象定义时调用一次,对应的析构函数在main终止或调用exit函数时调用。
#include <iostream> using namespace std; class A { public: A( int value ) { i = value; cout << "Object "<<i<<" constructor"; } ~A() // destructor { cout <<"Object "<<i<<" destructor"<< endl; } private: int i; }; A first(1); // global object全局变量 void func() { A fifth(5); cout <<" (local automatic in create)"<< endl; static A sixth( 6 ); cout <<" (local static in create)"<< endl; A seventh(7); cout <<" (local automatic in create)"<< endl; } int main() { cout <<" (global created before main)" <<endl; A second(2); cout <<" (local automatic in main)"<< endl; static A third(3); // local object cout <<" (local static in main)"<< endl; func(); // call function to create objects A fourth(4); // local object cout <<" (local automatic in main)"<< endl; return 0; }
程序执行结果为:
Object 1 constructor (global creasted before main)
Object 2 constructor (local automatic in main)
Object 3 constructor (local static in main)
Object 5 constructor (local automatic in create)
Object 6 constructor (local static in create)
Object 7 constructor (local automatic in create)
Object 7 destructor
Object 5 destructor
Object 4 constructor (local automatic in main}
Object 4 destructor
Object 2 destructor
Object 6 destructor
Object 3 destructor
Object 1 destructor
原文:https://www.cnblogs.com/wkfvawl/p/10620639.html