• 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...
    ");
        
        *p = 5;
        
        printf("c = %d
    ", c);
        
        printf("End...
    ");
        
        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
    ", a);
        //printf("b = %d
    ", 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
    ", 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/

  • 相关阅读:
    关于MySql 数据库InnoDB存储引擎介绍
    .netcore 中使用开源的AOP框架 AspectCore
    C#关于反序列化实例时,接收实体字段少于或大于原实体对象 解析测试
    PostgreSQL TIMESTAMP类型 时间戳
    C# 新特性 操作符单?与??和 ?. 的使用
    PostgreSQL 常用函数
    AutoCAD.Net/C#.Net QQ群:193522571 previewicon生成的块图标太小,CMLContentSearchPreviews生成大的图片
    C#winform中OpenFileDialog的用法
    C# winform datagridview 无需点击两次即可编辑内嵌控件的方法和删除默认的空行的方法
    C# winform datagridview 内嵌控件值改变后立即触发事件,而不需要离开该单元格时才触发,此时需要用到dgv_CurrentCellDirtyStateChanged事件
  • 原文地址:https://www.cnblogs.com/askta0/p/12732121.html
Copyright © 2020-2023  润新知