本节知识点:1.const和引用的疑惑: a.什么是符号表:符号表是编译器在编译过程中产生的关于源程序中语法符号的数据结构,如常量表、变量名表、数组名表、函数名表等等。符号表是编译器自用的内部数据结构,不会进入最终产生的可执行程序中。 b.只有用字面量初始化的const常量才会进入符号表: 只有const int a = 8; 这样的语句a才能进入符号表。像const int b = c; 或者 const int* b = (int*)(0x11223344); 这样的语句都使b变量变成了一个只读变量,b不存放在符号表中。还有就是volatile属性的const常量也不会进入符号表中,volatile const int b = 8; 语句中的b变量也一个只读变量,每次访问都从内存中取值。对于这些退化成为只读变量的常量,他们有地址有内存空间,且这个内存空间中存放着变量的值。对于存在符号表中的常量a来说,也可以对它取地址,和取引用,同样会使编译器为a分配一个内存空间,但是这个内存空间不会被使用(分配空间仅仅是为兼容c语言准备的),a常量是存在符号表中的。
c.const引用的类型与初始化变量的类型相同:
int a = 9; const int& b = a; 我们都知道const引用,是个常引用,因为它本质是个引用是个指针,所以它不可能存在符号表中,它是一个只读变量。当与初始化类型相同的时候,b引用仅仅是a的一个别名,与a同属一个内存地址空间,也就是说&a与&b值相同。改变a的时候,b的值也会跟着改变(即b还是a的引用)。
const引用的类型与初始化变量的类型不相同:
char a = 9; const int& b = a; 此时b引用当然还是一个只读变量。但是此时的b引用是编译器新产生的一只读变量了,仅仅是这个只读变量b的初始化是a的值。b已经不再是a的引用了,因为b是编译器新分配内存空间的一个只读变量了,&a与&b的值也不相同了,改变a的时候,b的值也不会跟着变了(a与b完全独立了)。这样我们就很容易理解,const int& b = 3; 的时候,b是一个初始值为3的只读变量(有内存,有地址)。
示例代码: [cpp]view plaincopy
3.重载的疑惑:a.c++编译器对字面量的处理方式:
整数型字面量的默认类型为int,占用4个字节;浮点型字面量的默认类型为double,占用8个字节;字符型字面量的默认类型为char,占1个字节;字符串型字面量的默认类型为const char*,占用4个字节。当使用字面量对变量进行初始化或赋值时,无溢出产生,编译器对字面量进行默认类型转换。有溢出产生,编译器会做出截断操作,并产生警告。 b.当重载函数的实参为变量并能够精确匹配参数时,不再进行默认类型转换匹配的尝试。当实参为字面量时,不同编译器处理方式不一样,g++是将字面量进行默认类型转换,然后进行精确匹配参数,成功,就不再进行类型转换的匹配了。有些编译器精确匹配参数成功后,还进行类型转换的匹配,导致int fun(int a, int b)和int fun(int a, char b) 对于fun(1,2)调用的时候,会产生二义性报错(g++不会的)!!!