深度探索C++ 对象模型【第六章1】

来源:互联网 发布:剑豪生死斗 知乎 编辑:程序博客网 时间:2024/06/06 11:12

1:如果对象仍然存活,而程序有一个以上的离开点,那么析构函数就会被放置在每一个离开点之前的位置,即使很有可能程序执行不到后面的离开点。所以一般而言,我们会将对象尽可能放置在使用它的那个程序区的附近,这样做可以节省非必要的对象产生和销毁操作。(用的时候再定义,会是一个好的选择)


2:对于全局对象而言,C++会保证在main()函数中第一次用到全局对象之前,把该全局对象构造出来而在main()函数结束之前把全局对象摧毁掉。全局变量放在data segment(数据段,用来保存已经初始化的全局对象)中。


3:如果全局对象没有显式的指定初值,那么该对象所配置的内存内容为0。


4:虽然类对象在编译期可以被放置于数据段中并且内容为0,但是其构造函数必须到程序启动时才会实施。


5:建议不要使用那些需要静态初始化的全局对象。


6:局部静态对象(local static object)

  • 其构造函数只能执行一次(即使是包含该静态对象的函数被执行多次)
  • 其析构函数只能执行一次(即使是包含该静态对象的函数被执行多次)
7:对于局部静态对象来说,只有包含它的函数被调用时,才会调用该对象的构造函数。

8:对象数组(array of objects)
  • 如果该对象的class没有构造及析构函数,那么相关的配置和内置类型的数组是一样的
  • 若该对象有一个默认的析构函数,那么该析构函数会轮流施行于每一个元素之上
  • 如果程序员提供或多个明显初值给一个由类对象组成的数组,对于明显获得初值的元素,将不再需要编译器内部的处理函数,对于那些没有获得初值的元素,将由编译器(cfront是vec_new函数进行初始化)
  • vec_new函数会调用该类的默认构造函数对数组中的对象进行初始化
9:对于对象数组来说,其内部的编译器实现较为复杂,要谨慎使用。

10:new和delete运算符 int *pi = new int(5);
  • 首先通过new运算符函数实例,分配适当的内存 int *pi = _new(sizeof(int));
  • 再将得到的对象设立初值 *pi = 5;
  • 进一步的,应当在第一步成功的情况下,进行第二步。

11:对于delete运算符,如果指针指向0,那么C++语言会要求delete运算符不要有操作,因此编译器必须为此调用构造一层保护:
if (pi != 0)
_delete(pi);
pi的值并不会因为delete操作被清除为0,因此后继的pi使用也是合法的。

12:delete操作作用于一个指针之后,该指针指向地址上的对象已经不再合法,但是地址本身却代表着一个合法的程序空间。(使用pi和使用pi所指向的对象是两个概念)

13:new运算符实际上总是以C标准的malloc()函数来完成的,相同,delete运算符也是以free()函数来完成的。

14:语言要求每一次对new的调用必须返回一个独一无二的指针,但是new T[0](无指针),出现后就必须解决这个问题,传统方法是返回一个指针,指向一个默认为1字节的内存区块。

15:编译器是否会产生临时对象,会视情况而定
  • NRV优化是否开启
  • operator+()的定义方式
  • 程序语境
某些情况下,编译器产生的临时对象是有必要的(或是比较方便的),临时变量的销毁是在对完整表达式求值的最后一步。