C/C++ 中const关键字的用法小结
C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性。
Const作用
NO. | 作用 | 说明 | 参考 |
---|---|---|---|
1 | 可以定义const常量 | constintMax=100; | |
2 | 便于进行类型检查 | const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误 | voidf(constinti){………}//对传入的参数进行类型检查,不匹配进行提示 |
3 | 可以保护被修饰的东西 | 防止意外的修改,增强程序的健壮性 | voidf(constinti){i=10;//error!}//如果在函数体内修改了i,编译器就会报错 |
4 | 可以很方便地进行参数的调整和修改 | 同宏定义一样,可以做到不变则已,一变都变 | |
5 | 为函数重载提供了一个参考 | classA{voidf(inti){……}//一个函数voidf(inti)const{……}//上一个函数的重载……}; | |
6 | 可以节省空间,避免不必要的内存分配 | const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝 | definePI3.14159//常量宏constdoulbePi=3.14159;//此时并未将Pi放入ROM中……doublei=Pi;//此时为Pi分配内存,以后不再分配!doubleI=PI;//编译期间进行宏替换,分配内存doublej=Pi;//没有内存分配doubleJ=PI;//再进行宏替换,又一次分配内存! |
7 | 提高了效率 | 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高 |
提到const都知道是修饰常量的,在一个变量前加上const关键字后这个常量就不可以再赋值了!
C语言中不是有#define吗,干嘛还要用const呢,我想事物的存在一定有它自己的道理,所以说const的存在一定有它的合理性,与预编译指令相比,const修饰符有以下的优点:
1、预编译指令只是对值进行简单的替换,不能进行类型检查
2、可以保护被修饰的东西,防止意外修改,增强程序的健壮性
3、编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
(以上三点摘抄自:https://www.nhooo.com/article/70831.htm)
const的应用
1定义常量
constinta=5; intconsta=5;
两种用法是一样的,这里变量a在第一次定义时复制后,在程序运行中就不可再赋值改变了;
例如:
intmain(intargc,char*argv) { constinta=5; intconstb=5; a=3;//编译时将会报错,常量不可修改 b=8;//编译时将会报错,常量不可修改 }
const用于修饰常量静态字符串,
例如:
constchar*Str="ABCDEFGH";
此时const修饰过的str就是常量我们不可更改Str的值如Str[3]='H';这时候是错误的,
2常量指针与指针常量
很多人往往分不清这两者的形态,
常量指针:
constint*pv;
intconst*pv;
两种定义方式一样,都是定义一个常量指针;即不可通过这个指针修改所指向地址的值;但是所指向的地址的值是可以通过其他变量指针修改的;
但是常量指针可以赋值新的指向地址;
例如:
intmain(intargc,char*argv) { inta=5; intb=7; constint*m=&a; intconst*n=&b; int*p=n;//把常量指针n指向的地址赋给p; *m=3;//编译时将会报错,常量指针不可修改所指向的地址的值 *n=8;//编译时将会报错,常量指针不可修改所指向的地址的值 *p=9;//编译无措,可以通过变量指针修改常量指针所指向的地址的值 m=&b;//编译无措,常量指针可以修改所指向的地址 n=&a;//编译无措,常量指针可以修改所指向的地址 }
指针常量
int*constpv;
是指这个指针指向的地址不可在改变,但指向的地址的值可以再改变;(指针常量是指指针本身是个常量,不能在指向其他的地址)
intmain(intargc,char*argv) { inta=5; intb=7; int*constm=&a; *m=8;//编译无措指针常量可以通过该指针修改所指向的地址的值 m=&b;//编译出错指针常量不可修改所指向想的地址 }
指向常量的常指针
常量指针结合指针常量即指向常量的常指针表示指针本身和指针所指向的地址在定义时赋值后都不可再改变;
定义如下:
constint*constp;
那么如何来区分常量指针和指针常量呢?
这就要明白关键字的结合优先级了,
如:constint*p;
以*优先级最高,先和int结合得到"int*"(读作整形指针)然后(int*)和const结合得到"const(int*)"(读作常量指针),然后才和p结合得到"(const(int*))p"(读作常量指针p),
int*constp;
同理,以*优先级最高,先和int结合得到"int*"(读作整形指针),然后(int*)和const结合得到"(int*)(const)"(读作指针常量),最后才和p结合得到"(int*)(const)p"(读作指针常量p)
3常量函数
常见的定义方式
classAA { public: voidmf_Fun1() { intb=10; num=b; } voidmf_Fun2()const { cout<在类成员函数的声明和定义中,const的函数不能对其数据成员进行修改操作。const的对象,不能引用非const的成员函数。
这儿的const就是说这个函数操作不会对变量或是对象之类的值有影响比如、有一个human类,现在要得到某个human类对象A的age那么肯定是不会因为想得到这个值而改变了age的大小,那么就可以写一个函数intgetAge()const这样就好这么做是为了防止在函数中对不应该在这里改变的量不小心进行了改变(抄录自https://zhidao.baidu.com/question/1702736835898870060.html)
4在什么情况下需要用到Const关键字?
4.1修饰函数的参数
根据常量指针与指针常量,const修饰函数的参数也是分为三种情况
1、防止修改指针指向的内容
voidStringCopy(char*strDestination,constchar*strSource);
其中strSource是输入参数,strDestination是输出参数。给strSource加上const修饰后,如果函数体内的语句试图改动strSource的内容,编译器将指出错误。
2、防止修改指针指向的地址
voidswap(int*constp1,int*constp2)
指针p1和指针p2指向的地址都不能修改。
3、以上两种的结合。
4.2修饰函数的返回值
如果给以“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const修饰的同类型指针。例如函数
constchar*GetString(void);
如下语句将出现编译错误:
char*str=GetString();
正确的用法是
constchar*str=GetString();
4.3修饰全局变量
全局变量的作用域是整个文件,我们应该尽量避免使用全局变量,因为一旦有一个函数改变了全局变量的值,它也会影响到其他引用这个变量的函数,
导致除了bug后很难发现,如果一定要用全局变量,我们应该尽量的使用const修饰符进行修饰,这样防止不必要的人为修改,使用的方法与局部变量是相同的。
4.4寄存器变量定义和寄存器读取
例如:
uint32_t*R0=(uint32*)0x400F00FF;//定义一个地址为0x400F00FF的32bit寄存器变量
正确的定义方法:
uint32_t*constR0=(uint32*)0x400F00FF;//定义一个指针常量R0指向地址为0x400F00FF的寄存器这样就保证变量R0指向的地址的唯一性,
若是指向一个只读寄存器则应该按如下定义:
constuint32_t*constR0=(uint32*)0x400F00FF;//定义一个指向常量的常指针R0指向地址为0x400F00FF的只读寄存器,这样就保证变量R0指向的地址的唯一性,同时不会因操作该指针修改指向地址的值
总结
到此这篇关于C/C++中const关键字的用法小结的文章就介绍到这了,更多相关C/C++const关键字内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。