《C++ Prime Plus》(4)

重载解析

 所谓重载解析,也即当程序中存在多个重载函数时编译器决定调用哪一个函数的分析过程。一般来说,调用重载函数的优先级为:较为具体的非模板函数>不够具体的非模板函数>较为具体的模板函数>不够具体的模板函数。

头文件:尖括号与引号之争

 使用尖括号#include<HeadFiles>时编译器将在存储标准头文件的主机系统的文件系统中查找该头文件;而使用引号#include "HeadFiles"时,编译器首先查找当前工作目录或源代码目录,如果没有找到才会再到标准位置查找。因此在包含标准库文件时最好使用尖括号,在包含用户自定义头文件时最好使用引号。

头文件:避免多次包含

 多文件编译时,常将结构定义,函数原型等放在头文件中,有时可能出现在多个代码文件中包含头文件的情况。使用预处理编译指令#ifndef能够避免这种情况:

1
2
3
4
#ifndef HEADFILE_H_
#define HEADFILE_H_ // 单纯定义名称,并不创建符号常量;
// content of head file
#endif

数据的存储持续性

 (1)自动存储持续性:

 在程序中正常定义的变量都为自动存储持续性。这类变量的数目在运行过程中会发生改变,编译器一般使用堆栈来管理此类变量。新数据被象征性的置于原有数据之上,通过两个堆栈指针分别指向栈顶和栈底来管理堆栈。例如,函数内部定义的变量处在调用程序变量的“上方”,当函数返回时栈顶指针又指回原先所在位置,此时在函数中定义的变量存放于堆栈中的数据并未被删除,但它们不再被标记,当有新的内存单元需求时,这些数据就会被覆盖。

 除了堆栈外,通过在变量声明前使用register关键字也可以请求将变量存入CPU寄存器中,这样的好处是访问该变量的速度很快。需要注意的是,对于此类变量,它们没有内存地址,因此无法执行取地址等操作。

 (2)静态持续变量

 这类变量的数目在程序运行过程中是不发生变化的,因此编译器分配固定大小的内存块来存储它们。如果没有显式地初始化静态持续变量,则编译器会默认其为0(对于数组元素、结构成员同样默认为0)。

 静态持续变量有三种。第一种具有外部链接性,直接定义在代码块外部(比如在main()之前定义的全局变量),作用范围最广,可以被程序中的其他文件使用;第二种具有内部链接性,同样定义在代码块外部但使用static限定符修饰它,只能在当前文件中使用;第三种没有链接性,定义在代码块内部并使用staic限定符修饰它,只能在当前语句块中使用。对于静态持续性变量,只能使用常量(表达式)来初始化它。

 对于具有外部链接性的静态持续变量(实际上就是全局变量),在首次定义(定义声明)时系统为其分配存储空间,此时可以对其进行初始化。在引用其他地方(函数)定义的变量的声明中应使用extern关键字,表示这是一个引用声明(而非定义声明),例如在文件1中定义了一个全局变量int global = 3;,如果要在文件2中使用这个全局变量,需要写一条用extern修饰的引用声明:extern int global;。此外,具有内部链接性的静态变量将隐藏同名的全局变量。例如在文件1中定义了int global = 3;,如果在文件2中定义static int global = 5;,这种定义是被允许的,且在文件2中global的值使用本文件中初始化的5,而非全局变量3。

 使用const定义的全局变量默认为具有内部链接性的静态持续变量,即该变量的作用范围为本文件。此外函数也具有链接性,所有函数在程序运行期间都是持续存在的且默认链接性为外部,即程序中的其他文件可以使用此函数,条件是使用此函数的文件需要在包含函数的原型。不过,内联函数不必遵守这项规定,如果程序员将内联函数放在头文件中,则包含此头文件的每个文件都有此内联函数的定义。

编译器对内存的使用

 编译器通常使用三块独立的内存:一块用于存放静态变量(可细分);一块用于存放自动变量;另一块用于动态存储,动态内存由newdelete控制。


转载请注明来源:©Tinshine