C++中Const说明

最近在看程序员面试宝典,看到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),修改会报段错误。

情况2(不在.rodata段分配空间):

  如果const用在局部并且没有使用static关键字,例如在main函数里面const int i=10*2+1,在这种情况下,如果对该常量:1)赋值是常量表达式(没有其它变量或者需要外界输入的值);2)不对该常量进行一些取地址类似的操作(&),就不会对i分配空间,仅仅是将其放在符号表中;否则,就会对i分配空间,而且这个空间是在栈上的,不同于全局的是分配在.rodata段上的。另外,注意,利用编译器反汇编的时候,可能会有一些假象,例如,在DEBUG模式下面的反汇编,编译器生成汇编代码为了能更好的调试,所以无论如何都会分配空间给const常量,但是如果你打开编译器的O2优化选项的话,就不会分配空间了。

  不过,不论分不分配空间,只要该常量的赋值是常量表达式(没有其它变量或者需要外界输入的值),编译器都会做一个优化,叫做常量折叠(const folding),简单来说,就是编译的时候,任何用到i的地方,都会直接用21去替换i。

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关键字是一个因素),局部下又可分为分配内存与不分配内存、有常量折叠和无常量折叠,分不分配内存取决于是否要对该常量进行地址相关的操作(如&或者直接从内存取值),有没有常量折叠取决于需不需要直接从内存中取值。

 

  有很多不足还请各位大神指出,大家相互学习相互进步,勿喷就好,谢谢啦

转载请说明出处

C++中Const说明,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。