C++学习笔记(二):进化后的const

0x01 对const关键字的误解

const是用来修饰变量的,const是constant的缩写,是恒定不变的意思,也翻译为常量和常数等。因为这一点很多人都认为const修饰的值是常量,这是错误的,精确的来说应该是只读的变量,它只是告诉编译器该变量不能出现在复制符号左边。

0x02 C语言中的const

const修饰的变量是只读的,本质还是变量。

const修饰的局部变量在栈上分配空间。

const修饰的全局变量在只读存储区分配空间。

const只在编译器有用,在运行期无用。

让我们通过一段小示例来看看在C语言中const修饰变量的上述几个特性。

#include <stdio.h>

int main()
{
    const int c = 0;
    int* p = (int*)&c;
    
    printf("Begin...\n");
    
    *p = 5;
    
    printf("c = %d\n", c);
    
    printf("End...\n");
    
    return 0;
}

通过运行结果可以看到,虽然变量c使用const修饰,但是在运行的时候,依然可以使用指针修改变量c的值。

通过上面的运行结果,我们可以看到,当将const修饰的变量定义为全局变量时,代码编译通过,但是运行却报了段错误,这就是由于const修饰的全局变量是定义在只读数据区的,因此根据只读数据区的特性,是无法对c变量的值进行修改,从而造成了段错误。

0x03 C++中的const

C++在C语言的基础上对const进行了进化处理,进化后的const主要拥有以下特性:

  • 当碰见const声明时在符号表中放入常量
  • 编译过程中若发现使用const修饰的常量则直接以符号表中的值替换
  • 编译过程中若发现下述情况则给对应的常量分配存储空间(C++编译器虽然可能会为const常量分配空间,但是不会使用其存储空间的值,目的是为了兼容C语言)。
    • 对const使用了extern
    • 对const使用了&操作符

0x04 const与宏定义

以下一段示例代码分别使用C编译器和C++编译器进行编译,结果如下:

#include <stdio.h>

void f()
{
    #define a 3
    const int b = 4;
}

void g()
{
    printf("a = %d\n", a);
    //printf("b = %d\n", b);
}

int main()
{
    const int A = 1;
    const int B = 2;
    int array[A + B] = {0};
    int i = 0;
    
    for(i=0; i<(A + B); i++)
    {
        printf("array[%d] = %d\n", i, array[i]);
    }
    
    f();
    g();
    
    return 0;
}

GCC编译器编译结果:

VS编译器编译结果:

通过不同编译器的编译运行结果可以得知:

c++中的常量类似于宏定义,比如int array[A+B] = {0}在c编译器中就报错,但是在c++编译器中没问题。

但是c++中的const常量与宏定义又是不相同的:

  • const常量是由编译器处理
  • 编译器const常量进行类型检查和作用域检查
  • 宏定义由预处理器处理,单纯的文本替换

所以进化后的const:

  • 是一个真正意义上的常量

  • 编译器可能会为常量分配空间

  • 完全兼容C语言中const常量的语法特性。

参考来源:http://www.dt4sw.com/

posted @ 2020-04-19 16:35  AskTa0  阅读(240)  评论(0编辑  收藏  举报