C++-Record07—C++中const的实现机制

目录

Const好处

Const实现原理

Const分配内存的时机 

Const的用途

总体代码


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;
}




发布了140 篇原创文章 · 获赞 6 · 访问量 4852

猜你喜欢

转载自blog.csdn.net/qq_17846375/article/details/103955006