一、对于C++中的const修饰的内部类型(build-in type)变量,除了以下几种情况,编译器是不会为其创建存储空间
a. 取一个const的地址
b. 把一个const作为一个带引用(指针)的参数传递给一个函数
c. 把它定义为extern
而当编译器不为其创建存储空间的时候,const是作为编译时常量来保存在编译器的符号表中(symboltable)的,在编译期间,会为编译时常量进行常量折叠(constant folding),也就是说,编译器会通过必要的计算,将一个复杂的常量表达式(constant expression)简化,然后进行替换。
而对于C中的const,意味着“一个不能被改变的普通变量(ordinary variant)”,所以是C编译器是会为const创建内存空间的,而且,在C中,默认的const连接方式为外部链接
二、头文件中的const
可以在头文件中定义const,这样,通过包含该头文件,可以把const定义单独放在一个地方,并把它分配给一个编译单元。c++的const默认是内部链接。也就是说,const仅在其被定义过的文件中才可见,在连接的时候,不能被其他编译单元看见。 (类似于被static修饰的变量)
三、类中的const变量:每一个类对象保存一个const实例,并为其分配空间
Inside a class,const partially reverts to its meaning in C. It allocates storagewithin each object and represents a value that is initialized once and then cannot change.
The use of const inside a class means“This is constant for the lifetime of the object.” However, each different object may contain a different value for that constant.
对于类中的const,只能在“构造函数初是的始化列表”中初始化,为什么?
因为const必须在建立它的地方初始化,所以在构造函数的主体里,const必定已经被初始化了。否则,就只能等到在构造函数主体以后的某
个地方给它初始化,这意味着,过一会儿才给const初始化,当然就无法防止在构造函数的主题的某些地方改变const的值。
四、C++中的const集合
C++中const可以用于集合,但是,编译器此时,不会将其保存到它的符号表中(symbol table),而是会为其分配分配内存,此时,const意味着“不能改变的一块存储空间(a piece of storage that cannot be changed)”。
五、与C语言中const的区别
如上所说,在C语言中,const是会被分配内存的,而且默认是外部链接,所以,像下面这种写法,在C编译器中是不通过的。
Const int buflen = 100;
int a[buflen]; //此时会报错误:error C2057: expected constant expression
但是,在C++中可以正常通过编译(通过上面的解释,你应该能清楚原因了吧?)
而与此相对应的:
Const int buflen
这种写法,在C编译器中可以通过编译,但是在C++中,却不能。为什么呢?
因为,在C++中,如果在const前不显示加上extern来表示外部链接,则表示是这个const的定义(注意,这里特别强调是定义,所以,必须初始化)。
而对于C这种默认const外部链接的情况,上面这种写法,则会被认为是声明(与C++对应,这里是声明),指明在别的地方有存储空间分配,所以,这样做是合理的。
六、最后总结提升:
a. 在C++中,因为const默认是内部链接,所以,你在两个文件中定义(再次强调)了同名的两个const,并不会造成连接错误,而在C中,是会的。
b. 在C++中,因为const默认是内部链接,所以在一个文件中定义一个const,而在另一个文件中没有用extern来声明而直接使用,则会报错,而在C中,是不会的。
c. 在C++中,对于如下的写法:
extern const int x = 1;
这种通过指定extern并进行初始化的const,我们强迫给它分配空间的。初始化使它成为定义,而不是声明(第N次强调定义和声明的区别,这在C++中显得尤为重要,在C中,因为它总会是一个定义,所以,初始化则不会显得那么必要)。当声明为extern const时,编译器就不回进行常量折叠了,因为它无法知道具体的值。(最后一句话,仔细体味体味。。。)