详解C++编程中的析构函数
C++析构函数 创建对象时系统会自动调用构造函数进行初始化工作,同样,销毁对象时系统也会自动调用一个函数来进行清理工作(例如回收创建对象时消耗的各种资源),这个函数被称为析构函数。 析构函数(Destructor)也是一种特殊的成员函数,没有返回值,不需要用户调用,而是在销毁对象时自动执行。与构造函数不同的是,析构函数的名字是在类名前面加一个”~“符号。 注意:析构函数没有参数,不能被重载,因此一个类只能有一个析构函数。如果用户没有定义,那么编译器会自动生成。 析构函数举例: #include <iostream> using namespace std; class Student{ private: char *name; int age; float score; public: //构造函数 Student(char *,int,float); //析构函数 ~Student(); //普通成员函数 void say(); }; Student::Student(char *name1,int age1,float score1):name(name1),age(age1),score(score1){} Student::~Student(){ cout<<name<<"再见"<<endl; } void Student::say(){ cout<<name<<"的年龄是 "<<age<<",成绩是 "<<score<<endl; } int main(){ Student stu1("小明",15,90.5f); stu1.say(); Student stu2("李磊",16,95); stu2.say(); Student stu3("王爽",80.5f); stu3.say(); cout<<"main 函数即将运行结束"<<endl; return 0; } 运行结果: 小明的年龄是 15,成绩是 90.5 李磊的年龄是 16,成绩是 95 王爽的年龄是 16,成绩是 80.5 main 函数即将运行结束 王爽再见 李磊再见 小明再见 可以看出,析构函数在 main 函数运行结束前被执行,并且调用顺序和构造函数正好相反,为了方便记忆,我们可以将之理解为一个栈,先入后出。 对象可以认为是通过类这种数据类型定义的变量,它的很多特性和普通变量是一样的,例如作用域、生命周期等。由此可以推断,对象这种变量的销毁时机和普通变量是一样的。 总结起来,有下面几种情况: 2) static 局部对象在函数调用结束时并不销毁,因此也不调用析构函数,只有在程序结束时(如 main 函数结束或调用 exit 函数)才调用 static 局部对象的析构函数。 3) 如果定义了一个全局对象,也只有在程序结束时才会调用该全局对象的析构函数。 4) 如果用 new 运算符动态地建立了一个对象,当用 delete 运算符释放该对象时,先调用该对象的析构函数。 注意:析构函数的作用并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作,使这部分内存可以分配给新对象使用。 C++调用构造函数和析构函数的顺序 可以简记为:先构造的后析构,后构造的先析构,它相当于一个栈,先进后出。 但是,并不是在任何情况下都是按这一原则处理的。对象可以在不同的作用域中定义,可以有不同的存储类别。这些会影响调用构造函数和析构函数的时机。 下面归纳一下什么时候调用构造函数和析构函数: 2) 如果定义的是局部自动对象(例如在函数中定义对象),则在建立对象时调用其构造函数。如果函数被多次调用,则在每次建立对象时都要调用构造函数。在函数调用结束、对象释放时先调用析构函数。 3) 如果在函数中定义静态(static )局部对象,则只在程序第一次调用此函数建立对象时调用构造函数一次,在调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用析构函数。 例如,在一个函数中定义了两个对象: void fn(){ Student stud1; //定义自动局部对象 static Student stud2; //定义静态局部对象 }
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |