构造函数在一个对象被建立需要声明的时候被调用,析构函数在对象释放时被调用。一般情况下,先构造的后析构,后构造的先析构。它相当于一个栈,先进后出。
对于在不同范围定义的对象,系统调用构造函数和析构函数的方式也有所不同。
1.全局范围:
在本文件模块所有函数(包括main函数)执行之前调用构造函数,当main函数执行完毕或者调用exit函数是,调用析构函数。
2.局部自动对象:
比如在函数中定义的对象。
建立对象时就要调用析构函数,如果该对象所在函数被多次调用,那么也要多次调用构造和析构函数(该对象的生命周期就是所在函数单次调用周期)
3.函数中定义的静态局部对象
只有在第一次调用所在函数定义对象时调用一次构造函数,函数调用结束时并不释放对象,只有在main函数结束或者调用exit函数时才会调用析构函数。
此处通过几段综合代码的运行来体现构造顺序。
#include<iostream>
#include<Windows.h>
using namespace std;
class A {
float x, y;
public:
A(float a, float b) { x = a; y = b; cout << "初始化自动局部对象\n"; }//带两个参数的构造函数一
A() { x = 0; y = 0; cout << "初始化静态局部对象\n"; }//无参(默认)构造函数二
A(float a) { x = a; y = 0; cout << "初始化全局对象\n"; }
//带一个参数的构造函数三
~A() { cout <<"调用析构函数"<< endl; }
//析构函数四
};
A a0(100.0); //定义全局对象,只有一个参数,调用三
void f() {n
cout << " 进入f()函数\n";
A ab(10.0, 20.0); //定义局部自动对象,两个参数,调用一
static A a3; //初始化局部静态对象 ,无参,调用二
}
void main() {
cout << "进入main函数\n";
f(); f();
}
运行结果:
本段代码中,先创建对象a0,调用到带一个参数的构造函数三,打印 “初始化全局对象”
编译流程继续,进入main主函数,打印“进入main”主函数;
调用f()函数,打印 “进人f()函数“;
此时建立局部自动对象ab,调用带两个参数的构造函数,打印 “初始化自动局部对象”;
建立静态局部对象a3,调用无参(默认)构造函数,打印 “初始化静态局部对象”;
第一个f()函数调用结束,内的局部对象ab释放掉,故打印 “调用析构函数”,但a3是函数中定义的静态局部对象,故在函数调用结束时对象不释放,此处不调用析构函数。
第二个f()函数被调用,此处打印 “进入f()函数”;
再建立局部对象ab,打印 “初始化自动局部对象”,而静态局部对象a3在上次定义中并没有释放,此处不再调用构造函数进行初始化。
main函数结束,三个对象均释放,打印三次 “调用析构函数”。