最近在看程序员面试宝典,看到const这块感受有很大疑惑,查了不少资料,能够总结以下:程序员
1.在C语言中面试
在C语言中,const修饰的变量不具备常量的特性,只是一个不可修改的变量,实质上仍然是变量,在编译期间没法知道它的值,不能够用做数组下标。数组
2.在C++中 函数
在C++中,const就有很大不同,C++中鼓励使用const来替代#define,在C++中对const定义的变量分为两种状况:学习
状况1(在.rodata段分配空间):优化
若是const用在全局或者使用了static关键字说明,例如extern const int i=10,static const int i=10。那么这个i就是一个常量(网上有人说真正意义上的常量),而且该常量是存放在.rodata段的,是没法经过取地址方式去修改的(具体状况见状况2),修改会报段错误。spa
状况2(不在.rodata段分配空间):调试
若是const用在局部而且没有使用static关键字,例如在main函数里面const int i=10*2+1,在这种状况下,若是对该常量:1)赋值是常量表达式(没有其它变量或者须要外界输入的值);2)不对该常量进行一些取地址相似的操做(&),就不会对i分配空间,仅仅是将其放在符号表中;不然,就会对i分配空间,并且这个空间是在栈上的,不一样于全局或是静态的是分配在.rodata段上的。另外,注意,利用编译器反汇编的时候,可能会有一些假象,例如,在DEBUG模式下面的反汇编,编译器生成汇编代码为了能更好的调试,因此不管如何都会分配空间给const常量,可是若是你打开编译器的O2优化选项的话,就不会分配空间了。内存
不过,不论分不分配空间,只要该常量的赋值是常量表达式(没有其它变量或者须要外界输入的值),编译器都会作一个优化,叫作常量折叠(constant folding),简单来讲,就是编译的时候,任何用到i的地方,都会直接用21去替换i。ci
a.有常量折叠
若是i的赋值是常量表达式(没有其它变量或者须要外界输入的值),即i的值不须要访问存储空间来肯定,那么程序中任何出现i的地方就已经在编译期间被替换,即便经过取地址来修改这个值,也是至关于改变了一个副本而已,以下:
const int i=1; int *p=(int *)&i; *p=2; cout<<*p<<endl<<i<<endl; 输出结果: 2 1 |
这说明,i的值是肯定的状况下,程序中任何出现i的地方都被1替换了。
b.无常量折叠
另外一种状况,若是赋值不是常量表达式,这时是须要访问存储区域才能获得确切值的,这种状况并不会有"常量折叠",以下:
int i=10; const char gc = cin.get(); //或者const char gc = i都是同样的 char *t = (char *)&gc; *t += 2; cout << *t <<endl << gc << endl; 输如:a 输出: c c |
从上面这个状况能够看出,虽然gc是局部的const,可是它的值是不肯定的,是须要用户输入的,所以会为gc在栈中分配空间,而且由于gc的值不肯定,它不能获得常量折叠带来的优化。程序中使用gc的地方,必须直接到存储区域去访问才能获得值,因此*t和gc的值是保持一致的。
无常量折叠的状况下,必定是分配了内存空间的,由于无常量折叠的本质就是值不肯定,须要到内存中获取。而有常量折叠的状况下,内存空间可能分配了,也可能没分配,若是分配了,那是由于对该常量进行了取地址相关的操做。
volatile关键字:
除此以外,volatile关键字也可以屏蔽掉常量折叠,以下:
volatile const int i=1; int *p=(int *)&i; *p=2; cout<<*p<<endl<<i<<endl; 输出结果: 2 2 |
上面是我查阅资料综合获得的状况,具体来讲,const使用状况可分为全局和局部(static关键字是一个因素),局部下又可分为分配内存与不分配内存、有常量折叠和无常量折叠,分不分配内存取决因而否要对该常量进行地址相关的操做(如&或者直接从内存取值),有没有常量折叠取决于需不须要直接从内存中取值。
有不少不足还请各位大神指出,你们相互学习相互进步,勿喷就好,谢谢啦
转载请说明出处