最近在看程序员面试宝典,看到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优化选项的话,就不会分配空间了。

  不过,不论分不分配空间,只要该常量的赋值是常量表达式(没有其它变量或者需要外界输入的值),编译器都会做一个优化,叫做常量折叠(constant 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说明的更多相关文章

  1. C、C++中const的区别

    C语言中: 被const修饰的变量,仍然是变量.虽然不能用C语法给这个变量改变值,但他本质上还是变量. C编译器会给它分配空间. C中,const默认使用的是外部链接. C++中: 被const修饰的 ...

  2. JavaScript中const、var和let区别浅析

    在JavaScript中有三种声明变量的方式:var.let.const.下文给大家介绍js中三种定义变量的方式const, var, let的区别. 1.const定义的变量不可以修改,而且必须初始 ...

  3. C/C++中const的用法 分类: C/C++ 2015-07-05 00:43 85人阅读 评论(0) 收藏

    const是C语言的关键字,经C++进行扩充,变得功能强大,用法复杂.const用于定义一个常变量(只读变量),当const与指针,引用,函数等结合起来使用时,情况会变得复杂的多.下面将从五个方面总结 ...

  4. C++中const 的各种用法

    C++中const 关键字的用法 const修饰变量 const 主要用于把一个对象转换成一个常量,例如: ; size = ; // error: assignment of read-only v ...

  5. (转) C/C++中const关键字详解

    文章转自  http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777416.html 为什么使用const?采用符号常量写出的代码更容易维 ...

  6. 实例讲述PHP面向对象的特性;;;php中const与define的使用区别

    php中const与define的使用区别 1.const:类成员变量定义,一旦定义且不能改变其值. define:定义全局常量,在任何地方都可以访问.2.define:不能在类中定义,而const可 ...

  7. C++中const简介及用法

    1.const简介 C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,本人根据各方面查到的资料进行总结如下,期望对朋友们有所帮助. Const 是C++中常用的类型修饰 ...

  8. C/C++ 中 const 修饰符用法总结

    C/C++ 中 const 修饰符用法总结 在这篇文章中,我总结了一些C/C++语言中的 const 修饰符的常见用法,供大家参考. const 的用法,也是技术性面试中常见的基础问题,希望能够帮大家 ...

  9. C++中const用法详解

    本文主要内容来自CSDN论坛: http://bbs.csdn.net/topics/310007610 我做了下面几点补充. 补充: 1. 用const声明全局变量时, 该变量仅在本文件内可见, 类 ...

  10. C++ 中 const和define的区别

    来源网址:http://wujiangping.blog.163.com/blog/static/195182011201255115125205/ 请区别用#define命令定义的符号常量和用con ...

随机推荐

  1. 基于内嵌Tomcat的应用开发

    为什么使用内嵌Tomcat开发? 开发人员无需搭建Tomcat的环境就可以使用内嵌式Tomcat进行开发,减少搭建J2EE容器环境的时间和开发时容器频繁启动所花时间,提高开发的效率. 怎么搭建内嵌To ...

  2. js key事件 keyCode大全

    keycode 8 = BackSpace BackSpace keycode 9 = Tab Tab keycode 12 = Clear keycode 13 = Enter keycode 16 ...

  3. 在js中获取easyui datagrid的数据

    可以在页面对datagrid的数据直接进行修改,然后提交到数据库,但是要求在提交前获取datagrid的所有行的数据.API提供了getData方法,但是怎么用了,没说. 最后这样写才搞定 var a ...

  4. 如何通过 OAuth 2.0 使 iOS Apps 集成 LinkedIn 登录功能?

    社交网络早已成为人们日常生活的一部分.其实,社交网络也是编程生活的一部分,大多数 App 必须通过某种方式与社交网络交互,传送或接收与用户相关的数据.大多数情况下,用户需要登录某种社交网络,授权 Ap ...

  5. [itint5]直角路线遍历棋盘

    http://www.itint5.com/oj/#22 这题一开始直接用暴力的DFS来做,果然到25的规模就挂了. vector<bool> visited(50, false); ve ...

  6. matlab 在代码中,显示错误,退出程序

    使用函数error('message_id', 'message'),出现错误时函数中止运行. 参考http://www.ilovematlab.cn/thread-43261-1-1.html

  7. RabbitMQ安装和配置

    RabbitMQ: MQ:message queue.MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来 ...

  8. 退出myeclipse 8.5配置中心

    用myeclipse 8.5没多久,进入软件中心下载插件,找不到退出按钮,唉,木想到就是一图标.

  9. log file sync

    Recently, our application system has updated one app. I receive a email of complain the db server ch ...

  10. 使用PHP处理POST上传时$_FILES数组为何为空

    在做一个简单的表单上传测试时,服务端的php脚本中,$_FILES数组为空;这样就不能获取从浏览器上传的信息.什么原因呢? 通过Google,找到下面这个web: php上传文件$_FILES数组为空 ...