Bootstrap

构造函数与析构函数的保护权限

    通常我们如果希望对象只在堆上创建,我们会将析构函数定义为protect或private类型,这种情况下我们还要添加一个函数来析构对象,因为此时在类外部无法使用delete释放对象,因为析构函数被保护,那么究竟为什么限制析构函数的访问权限可以避免栈对象被创建呢,详细原因如下:

    我们来分析类对象的内存分配与释放问题:栈对象和堆对象。

    1、栈空间的对象是编译器自动完成初始化与释放的,它的原理是在编译阶段编译器就会为一个栈对象分配空间(这里分配空间指的是按一定规则分配地址,并不是真正的分配内存空间,那什么时候分配内存呢,在程序装载是会对编译器已分配的地址进行重定向,重定向的概念还记得吧,重定向之后这些地址便有了真正的内存与之对应了),并自动调用构造函数和析构函数(作用域结束的地方),这样一来就必须知道构造函数与析构函数的定义。堆空间大小有限,过多的栈对象会导致栈溢出,由于栈对象是在编译阶段分配地址的,如果地址不够用编译阶段会报错。

   2、堆空间的对象是在运行时期动态创建与释放的,这个工作有程序员自己完成,因此,编译器在遇到创建堆对象代码时,会自动调用operator new()函数来分配内存,之后会调用该对象的构造函数来完成初始化,但并不自动调用析构函数。

    经过分析我们可以知道栈对象会调用构造函数和析构函数,堆对象会调用operator new和构造函数,很明显限制析构函数的访问权限会导致栈对象不能使用而堆对象不受影响。

    这里延伸记录一下关于程序内存问题,编译器会在编译阶段为类、函数、静态和全局变量等规划地址,这些地址一般划分区域为:数据区、代码区、栈区和堆区,因此不是自己以前想象的大部分地址都是运行时才确定,比如类的成员函数,所有对象的成员函数地址是相通的,在编译阶段已经确定的(一般在代码区),而对象一般仅包含成员变量(数据区、栈区或堆区),两者在地址并不相关,不要企图用对象地址来获取函数地址。

;