C++学习笔记(二):进化后的const
0x01 对const关键字的误解
const是用来修饰变量的,const是constant的缩写,是恒定不变的意思,也翻译为常量和常数等。因为这一点很多人都认为const修饰的值是常量,这是错误的,精确的来说应该是只读的变量,它只是告诉编译器该变量不能出现在复制符号左边。
0x02 C语言中的const
const修饰的变量是只读的,本质还是变量。
const修饰的局部变量在栈上分配空间。
const修饰的全局变量在只读存储区分配空间。
const只在编译器有用,在运行期无用。
让我们通过一段小示例来看看在C语言中const修饰变量的上述几个特性。
#include <stdio.h>
int main()
{
const int c = 0;
int* p = (int*)&c;
printf("Begin...\n");
*p = 5;
printf("c = %d\n", c);
printf("End...\n");
return 0;
}
通过运行结果可以看到,虽然变量c使用const修饰,但是在运行的时候,依然可以使用指针修改变量c的值。
通过上面的运行结果,我们可以看到,当将const修饰的变量定义为全局变量时,代码编译通过,但是运行却报了段错误,这就是由于const修饰的全局变量是定义在只读数据区的,因此根据只读数据区的特性,是无法对c变量的值进行修改,从而造成了段错误。
0x03 C++中的const
C++在C语言的基础上对const进行了进化处理,进化后的const主要拥有以下特性:
- 当碰见const声明时在符号表中放入常量
- 编译过程中若发现使用const修饰的常量则直接以符号表中的值替换
- 编译过程中若发现下述情况则给对应的常量分配存储空间(C++编译器虽然可能会为const常量分配空间,但是不会使用其存储空间的值,目的是为了兼容C语言)。
- 对const使用了extern
- 对const使用了&操作符
0x04 const与宏定义
以下一段示例代码分别使用C编译器和C++编译器进行编译,结果如下:
#include <stdio.h>
void f()
{
#define a 3
const int b = 4;
}
void g()
{
printf("a = %d\n", a);
//printf("b = %d\n", b);
}
int main()
{
const int A = 1;
const int B = 2;
int array[A + B] = {0};
int i = 0;
for(i=0; i<(A + B); i++)
{
printf("array[%d] = %d\n", i, array[i]);
}
f();
g();
return 0;
}
GCC编译器编译结果:
VS编译器编译结果:
通过不同编译器的编译运行结果可以得知:
c++中的常量类似于宏定义,比如int array[A+B] = {0}在c编译器中就报错,但是在c++编译器中没问题。
但是c++中的const常量与宏定义又是不相同的:
- const常量是由编译器处理
- 编译器const常量进行类型检查和作用域检查
- 宏定义由预处理器处理,单纯的文本替换
所以进化后的const:
-
是一个真正意义上的常量
-
编译器可能会为常量分配空间
-
完全兼容C语言中const常量的语法特性。
~欢迎各位师傅关注我的公众号哟~