const在C与C++中的区别

  • 在C中,const不是常量,只能说是一个不能改变的变量(注意是变量),C编译器不能把const看成看成一个编译期间的常量,因为他在内存中有分配,C编译器不知道他在编译期间的值。所以不能作为数组定义时的下标,因为它必须为常量。

  • 在C中,const int a;是可以的,因为这只是声明一个变量,告诉编译器,我这里是声明,指明在别的地方有内存分配。但在C++中这样写是不正确的,C++中const默认是内部链接,C中默认是外部链接,为了起到和c语言一样的效果,C++需要将const修饰为extern,因为extern优先级高于const,所以变量会被变为extern外部链接,起到和C语言一样的效果。[(1)内连接:编译器只对正被编译的文件创建存储空间,别的文件可以使用相同的表示符或全局变量.C/C++中内连接使用static关键字指定.(2)外连接:所有被编译过的文件创建一片单独存储空间.一旦空间被创建,连接器必须解决对这片存储空间的引用.全局变量和函数使用外部连接.通过extern关键字声明,可以从其他文件访问相应的变量和函数.] 通俗的讲:在c++ 中const 对象默认为文件的局部变量。与其他变量不同,除非特别说明,在全局作用域声明的 const变量是定义该对象的文件的局部变量。此变量只存在于那个文件中,不能被其他文件访问。通过指定 const 变更为extern,就可以在整个程序中访问 const 对象。

  • C++中是否为const分配内存空间要看具体情况,如果被声明为extern或者取const变量地址,就需要为const变量分配空间。

  • 当在自己的文件中使用const的时候,C++不会为const常量分配空间,因为这是一种优化措施,没有必要浪费空间去存储一个常量,此时const int a=5 就相当于#define a 5,当在其他文件使用的时,需要分配内存,同样在程序内部引用的时候,也需要分配内存,因为这两者都是采用寻址的技术去使用的,不分配内存就没有地址。C++中定义常量的时候不再采用define,因为define只做简单的宏替换,并不提供类型检查。

  • C++中用const定义了一个常量后,不会分配一个空间给它,而是将其写入符号表(symbol table),这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。但是const定义的常量本质上也是一个变量,是变量就会有地址,那么什么时候会分配内存?

  int main()
  {
      const int a = 2;
      int* p = (int*)(&a);
      *p = 30;
      cout << &a << endl;
      cout << p << endl;
      cout << a << endl;
      cout << *p << endl;
      return 0;
 }
  
 /*运行结果:
 -----------
 010FF958
 010FF958
 2
 30
 -----------
 */
  • 通过 intp = (int)(&a);这种方法,可以直接修改const常量对应的内存空间中的值,但修改不会影响到常量本身的值,因为用到a的时候,编译器根本不会去进行内存空间的读取。这就是C++的常量折叠constant folding,即将const常量放在符号表中,而并不给其分配内存。编译器直接进行替换优化。除非需要用到a的存储空间的时候,编译器迫不得已才会分配一个空间给a,但之后a的值仍旧从符号表中读取,不管a的存储空间中的值如何变化,都不会对常量a产生影响。

  • 但是在C语言中却不是这样,C没有constant folding的概念,用const定义一个常量的时候,编译器会直接开辟一个内存空间存放该常量。不会进行优化。同样的例子在C下面会产生不同的结果:
 int main()
 {
      const int a = 2;
      int* p = (int*)(&a);
      *p = 30;
      cout << &a << endl;
      cout << p << endl;
      cout << a << endl;
      cout << *p << endl;
      return 0;
 }
  
 /*运行结果:
 -----------
 010FF958
 010FF958
 2
 30
 -----------
 */
 
  • C中,一个被const定义为常量的值,却能被修改,而且编译器不报任何错误。进一步深入可发现,对于以上两个例子来说,a都是定义在某个函数之内的(比如main()函数),不管是C还是C++,本质上都只是将其当成一个普通的局部变量来对待,都只是在栈上分配空间。所以const根本就不能起到阻止修改其内存空间的作用,一个合法的强制类型转换就可以轻松搞定。C++比C好的地方就在于使用了constant folding的机制,使得常量的值跟对应的内存空间无关,从而保护了该常量值。

  • 以上的例子针对局部的const常量而言,对全局的const变量,C++仍旧采用constant folding策略,故以下代码是行得通的:
const int a = 3;
 int arr[a];
  • 但C会报错: error: variably modified ‘arr’ at file scope,原因在于GCC认为a只是一个普通的全局变量,而变量是不能用来指定数组的长度的,这是针对全局数组而言。但如果是局部的数组的话,就算是int a = 3; int arr[a];这种都是可以的,若在C和C++中如果我们仍然用int p = (int)(&a);这种方法来修改它内存中的值,编译时不会报错,但是运行时会报错误,因为a是放在只读的全局数据区中,修改该区中的数据会引发段错误。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值