目录
const在C与C++中的表现是不一样的!
先捋顺const在C中的表现:
详情请翻阅:https://blog.csdn.net/qq_17846375/article/details/103832813
Const好处
1.合理的利用const;2.一指针做函数参数,可以有效的提高代码可读性,减少bug;3.二清楚的分清参数的输入和输出特性
Const实现原理
C++中的Const是个main函数,先看一段代码(在C编译器中运行):
void main82()
{
//好像 a 是一个常量
const int a = 10;
//a = 11;
printf("a:%d \n", a);
system("pause");
}
如果不把"a = 11;"给注释掉,就会报错,这样好像可以证明a是一个常量,不可被修改,再往下看(在C编译器中运行):
void main82()
{
//好像 a 是一个常量
const int a = 10;
//a = 11;
int *p = NULL;
p = (int *)&a;
*p = 20; //间接赋值
printf("a:%d \n", a);
printf("*p:%d \n", *p);
system("pause");
}
运行结果:
可以看出,通过指针的方式去间接修改a,也是可以修改成果的,可见const并不是很靠谱。这说明C语言中的const是一个冒牌货。同样的代码,看看在C++编译器中的表现:
会发现,a竟然没通过间接修改而改变,同时,也没报错,还能运行出来!从现象来看,C++语言当中,const是一个真正的常量。
C++编译器,会把a放在一个符号表里面,符号表的存在形式是一个名词对儿,对应的a的值是10,就写死了,(注意,这里的符号表存放的位置,并不是内存四区,C++的内存控制跟之前说的内存四区,已经不是一个机制了!),当使用a的时候,就把对应的值“10”拿出来,供你使用,而当对变量a取地址的时候,C++编译器会为变量a再单独的开辟一块内存空间,然后,再把这个内存空间取地址,赋给了一个指针变量p,相当于指针p指向了这个新开辟的内存空间,但并不是原来的名词对儿存放的位置,通过"*p",去间接的修改值,修改的是新开辟一块儿内存空间中存的值,而不是原来的a的值,虽然,其实存放的值是一样的,但是,通过指针间接修改的时候,不管怎么修改,都不会影响原来a的值,还能修改成果,这就是为啥a的值不会变,而且,程序还能运行的缘故了!
通过这种方式,将被const修饰的变量,变成了真正意义上的常量!
思路图如下:
当然,可以借着把*p指向的空间值给打印出来更印证我们的设想。
注意:
C++编译器虽然可能为const常量分配空间,但不会使用其存储空间中的值。
结论:
C语言中const变量是只读变量,有自己的存储空间。
C++中的const常量,可能分配存储空间,也可能不分配存储空间,当const常量为全局,并且需要在其它文件中使用时,应该使用&操作符取const常量的地址。
补充:
当一个变量被别的文件引用的时候,C++编译器也会为其分配一个额外的内存空间。
Const分配内存的时机
接着上面的思路问一个问题:上面所提到的分配额外的内存,是在编译器执行阶段还说编译器编译阶段分配的呢?
答案是在编译器编译期间来分配的,当扫描到对应的代码行的时候,就会进行内存的分配。如下代码可以进行证明:
//3 const分配内存的时机 编译器编译器期间
void main83()
{
//好像 a 是一个常量
int a;
const int b = 10;
int c;
printf("&a:%d, &b:%d, &c:%d \n", &a, &b, &c);
system("pause");
}
运行结果如下:
会发现内存编号逐渐减少。确确实实b是处于a与c之间的,说明是在扫描的过程中进行的内存分配。
Const的用途
Const是C++里面用来替换#define(宏定义)的一个手段,在C语言中,通过#define,来做一个宏替换,相同之处:
//4const 和 #define的相同之处
//#define, 在编译预处理阶段 处理
//const常量是由编译器处理的,提供类型检查和作用域检查
#define d 20
void main84()
{
//int a = 10;
//int b = 20;
//int array[a+b]; //linux内核里面是成立的;原因 编译linux内核的gcc编译器支持.
//c和c++编译器 不支持这种语法现象
const int c = 10;
//const int d = 20;
int array2[c+d];
system("pause");
}
上面被注释的部分不能在C++编译器中被通过,而下面的c经过const后,可以被编译通过,说明在这个案例下,const的作用和#define是相同的。
但是,他们也有不同的地方:
#define,是在编译预处理阶段处理的,而const常量是在编译器处理的;
const还可以提供类型检查和作用域检查,而#define不能。
//5 const定义的变量,由编译器处理的,提供类型检查和作用域检查
void fun1()
{
#define a 10
const int b = 20;
//#undef a
//# undef
}
void fun2()
{
printf("a = %d\n", a);
printf("b = %d\n", b);
}
int main()
{
fun1();
fun2();
return 0;
}
#define是全局的,只有定义,所有域都能使用,容易造成冲突。
const所定义的变量是有作用域的,只能在fun1中使用,不能再fun2中使用。
总体代码
dm08_const的基础用法.cpp
#include <iostream>
using namespace std;
//0 const的基础知识
struct Teacher
{
char name[64];
int age;
};
//指针所指向的内存空间,不能被修改
int operatorTeacher01(const Teacher *pT)
{
//pT->age = 10;
return 0;
}
//指针变量本身不能被修改
int operatorTeacher02( Teacher * const pT)
{
pT->age = 10;
//pT = NULL; //
return 0;
}
int operatorTeacher03( const Teacher * const pT)
{
//pT->age = 10;
//pT = NULL; //
printf("age:%d", pT->age);
return 0;
}
void main81()
{
// const int a;
// int const b; //一样
//
// const int *c; //const修饰的是指针所指向的内存空间,不能被修改
// int * const d; //
// const int * const e ;
cout<<"hello..."<<endl;
Teacher t1;
t1.age = 33;
operatorTeacher03(&t1);
system("pause");
return ;
}
//1
//c语言中的const是一个冒牌货
//C++语言中 const是一个真正的常量
//2 原因分析
//const int b = 10; 符号表
void main82()
{
//好像 a 是一个常量
const int a = 10;
//a = 11;
int *p = NULL;
p = (int *)&a;
*p = 20; //间接赋值
printf("a:%d \n", a);
printf("*p:%d \n", *p);
system("pause");
}
//3 const分配内存的时机 编译器编译器期间
void main83()
{
//好像 a 是一个常量
int a;
const int b = 10;
int c;
printf("&a:%d, &b:%d, &c:%d \n", &a, &b, &c);
system("pause");
}
//4const 和 #define的相同之处
//#define, 在编译预处理阶段 处理
//const常量是由编译器处理的,提供类型检查和作用域检查
#define d 20
void main84()
{
//int a = 10;
//int b = 20;
//int array[a+b]; //linux内核里面是成立的;原因 编译linux内核的gcc编译器支持.
//c和c++编译器 不支持这种语法现象
const int c = 10;
//const int d = 20;
int array2[c+d];
system("pause");
}
//5 const定义的变量,由编译器处理的,提供类型检查和作用域检查
void fun1()
{
#define a 10
const int b = 20;
//#undef a
//# undef
}
void fun2()
{
printf("a = %d\n", a);
printf("b = %d\n", b);
}
int main()
{
fun1();
fun2();
return 0;
}