c和c++关于const的一些区别

如下参考了网上的一些资料并经过程序验证。c++

注意,如下状况都是用gcc和g++编译器获得的结果,用vs编译器又会有所不一样。数组

如下说下c和c++中const定义的常量的一些区别:函数

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;
}

结果:spa

咱们看到,经过 int*p = (int*)(&a);这种方法,能够直接修改const常量对应的内存空间中的值,可是这种修改不会影响到常量自己的值,由于用到a的时候,编译器根本不会去进行内存空间的读取。这就是c++的常量折叠(constant folding),即将const常量放在符号表中,而并不给其分配内存。编译器直接进行替换优化。除非须要用到a的存储空间的时候,编译器无可奈何才会分配一个空间给a,但以后a的值仍旧从符号表中读取,无论a的存储空间中的值如何变化,都不会对常量a产生影响。code

可是在c中却不是这样.c没有constant folding的概念,用constant定义一个常量的时候,编译器会直接开辟一个内存空间存放该常量。不会进行优化。一样的例子在c下面会产生不一样的结果:blog

 1 int main()
 2 {
 3     const int a  = 2;
 4     int* p = (int*)(&a);
 5     *p = 30;
 6     printf("%x\n",&a);
 7     printf("%x\n",p);
 8     printf("%i\n",a);
 9     printf("%i\n",*p);
10     return 0;
11 }

结果:内存

咱们看到,在c里面,一个被const定义为常量的值,冠冕堂皇地被修改了,并且编译器没有报任何错误 !编译器

若是咱们进一步深刻能够发现,对于以上两个例子来讲,a都是定义在某个函数以内的(好比main()函数),无论是c仍是c++,本质上都只是将其当成一个普通的局部变量来对待,都只是在栈上分配空间。因此const根本就不能起到阻止修改其内存空间的做用,一个合法的强制类型转换就能够轻松搞定。c++比c好的地方就在于使用了constant folding的机制,使得常量的值跟对应的内存空间无关,从而保护了该常量值。it

以上的例子是针对局部的const常量而言,对全局的const变量,c++仍旧采用constant folding策略,故如下代码是行得通的:

//global variable
const int a = 3;
int arr[a];

可是c会报错: error: variably modified 'arr' at file scope, 缘由在于gcc认为a只是一个普通的全局变量,而变量是不能用来指定数组的长度的。固然,这是针对全局数组而言,若是是局部的数组的话,就算是int a = 3; int arr[a];这种都是能够的,由于c里面还有一种叫变长数组的东西(我晕~,貌似由于二者的实现机制不同,这个要再看看)

另外,对于a,在c和c++中若是咱们仍然用int *p = (int*)(&a);这种方法来修改它内存中的值,编译时不会报错,可是运行时会报段错误,由于a是放在只读的全局数据区中,修改该区中的数据会引起段错误。

 

在vs编译器下:

1.不支持变长数组,一个变量除非被声明为const,不然不能用来声明数组的长度。

2.const变量,无论是全局的仍是局部,都是放在只读数据区,因此没法用前面的方法来修改内存空间里面的值,编译时就会报错。

相关文章
相关标签/搜索