C++的new云算子和C的malloc函数都是用于配置内存的,但是前者比之后者的优点是,new不但配置对象所需要的内存空间,同时会引发构造函数的执行。
所谓的构造函数(constructor),就是对象诞生后第一个执行(并且自动执行)的函数,它的函数名称必定要与类名称相同。
相对于构造函数,自然就有个解构(析构)函数,也就是在对象行将毁灭但未毁灭之前一刻,最后执行(并且自动执行)的函数,它的函数名称必定要与类名称相同,再在最前面加一个~符号。
一个有层次结构的类群租,当派生类的对象诞生之时,构造函数的执行是由最基类至最尾端派生类;当对象毁灭之前,解构函数的执行则是反其道而行。
对于构造函数和解构函数的执行的时间,针对不同的对象共可以分为四类:
1、对于全局对象(包括静态全局对象),程序一开始,其构造函数就先被执行(比程序进入点更早);程序即将结束前其解构函数被执行。 定义全局对象如下: CFoo foo; //在任何函数范围之外做此操作
由于对象实现于任何“函数活动范围”之外,显然没有地方安置这样一个构造函数调用操作。这种静态全局对象的构造函数调用操作必须靠startup码帮忙。startup码是更早于程序进入点(main或winMain)执行起来的码,由C++编译器提供,被链接到你的程序中。startup码可能做些像函数库初始化、行程信息设立、I/O stream产生等等操作,以及对static对象的初始化操作(也就是调用其构造函数)。
当编译器编译你的程序,发现一个静态对象时,它会把这个对象加到一个连表中。更精确的说,编译器不只是加上这个静态对象,它还加上一个指针,指向对象之构造函数及其参数(如果有的话)。把控制权交给程序进入点(main或WinMain)之前,startup码会快速在该连表上移动,调用所有登记在案的构造函数并使用登记在案的参数,于是就初始化了你的静态对象。
2、对于局部对象,当对象诞生时,其构造函数被执行;当程序流程将离开该对象的存活范围(以至于对象将毁灭)时,其解构函数被执行。
void MyFunc()
{
CFoo foo; //在堆栈(stack)中产生foo对象
}
这种局部情况C++在配置内存---来自堆栈(stack)或堆(heap)---之后立刻产生一个隐藏的(代码中看不出来的)构造函数调用。
3、对于静态(static)对象,当对象诞生时其构造函数被执行;当程序将结束时(此对象因而将遭致毁灭)其解构函数才被执行,但比全局对象的解构函数早一步执行。
void MyFunc()
{
static CFoo foo; //在函数范围之内的一个静态对象
}
这种局部静态变量相当于C语言中的静态局部变量,只会有一个实例(instance)产生,而且在固定的内存上(既不是stack也不是heap)。它的构造函数在控制权第一次转移到其声明处(也就是MyFunc第一次被调用)时被调用。
4、对于以new方式产生出来的局部对象,当对象诞生时其构造函数被执行。解构函数则在对象被delete时执行。
void MyFunc()
{
CFoo* pFoo = new CFoo(); //在堆(heap)中产生对象
}
C++在配置内存之后立刻产生一个隐藏(程序代码看不出来的)构造函数调用。