zoukankan      html  css  js  c++  java
  • C++解析(2):进化后的 const 分析

    0.目录

    1.C语言中的const

    2.C++中的const

    3.对比

    4.小结

    1.C语言中的const

    • const修饰的变量是只读的,本质还是变量
    • const修饰的局部变量在栈上分配空间
    • const修饰的全局变量在只读存储区分配空间
    • const只在编译期有用,在运行期无用

    也就是说:const修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边。
    (如果我们修改了const修饰的全局变量,那么程序将产生一个崩溃,因为我们修改了只读存储区里面的内容,那么大多数编译器所编译出来的可执行程序都会发生崩溃的。)

    • C语言中的const使得变量具有只读属性
    • const将具有全局生命周期的变量存储于只读存储区

    综上,const不能定义真正意义上的常量!
    (面试题:在C语言里面,你有办法定义真正的常量吗?
    如果回答:可以,用const。//C语言一般
    因为在C语言里面只有通过enum来定义的这些标识符才是真正意义上的常量,也就是说,C语言里面真正意义上的常量只有枚举。const只不过说使得变量具有了只读属性而已,它并不能定义真正意义上的常量。)

    那么C++中的const到底有什么改变呢?
    这是test.c代码:

    // test.c
    #include <stdio.h>
    
    int main()
    {
        const int c = 0;
        int* p = (int*)&c;
        
        printf("Begin...
    ");
        
        *p = 5;
        printf("c = %d
    ", c);
        printf("*p = %d
    ", *p);
        
        printf("End...
    ");
        return 0;
    }
    

    这是test.cpp代码:

    // test.cpp
    #include <stdio.h>
    
    int main()
    {
        const int c = 0;
        int* p = (int*)&c;
        
        printf("Begin...
    ");
        
        *p = 5;
        printf("c = %d
    ", c);
        printf("*p = %d
    ", *p);
        
        printf("End...
    ");
        return 0;
    }
    

    分别用gcc编译器和g++编译器运行程序结果如下:

    [root@bogon Desktop]# gcc test.c
    [root@bogon Desktop]# ./a.out 
    Begin...
    c = 5
    *p = 5
    End...
    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    Begin...
    c = 0
    *p = 5
    End...
    

    2.C++中的const

    C++在C的基础上对const进行了进化处理

    • 当碰见const声明时在符号表中放入常量

    • 编译过程中若发现使用常量则直接以符号表中的值替换

    • 编译过程中若发现下述情况则给对应的常量分配存储空间:

      1. const常量使用了extern
      2. const常量使用&操作符

    注意:C++编译器虽然可能为const常量分配空间,但不会使用其存储空间中的值。
    (为什么会有这种行为?这是为了兼容C语言。兼容的意思是说,之前能用C语言编译器编译的程序,用C++编译器也要能编译通过。只不过说编译通过了以后,可能可执行程序运行的结果会有所不同。)


    (符号表就是编译器在编译的过程当中所产生的一张表,这张表是编译器内部的数据结构,也就是说,编译器在编译程序的时候会产生各种各样的数据结构,这些内部的数据结构里面就有一个叫做符号表。)

    3.对比

    3.1 C语言与C++中的const

    C语言中const变量是只读变量,会分配存储空间

    C++中的const可能分配存储空间

    • const变量为全局,并且需要在其它文件中使用
    • 当使用&操作符对const常量取地址

    这是test.c代码:

    // test.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;
    }
    

    这是test.cpp代码:

    // test.cpp
    #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编译器和g++编译器运行程序结果如下:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# gcc test.c
    test.c: In function ‘main’:
    test.c:20: error: variable-sized object may not be initialized
    test.c:20: warning: excess elements in array initializer
    test.c:20: warning: (near initialization for ‘array’)
    
    • C语言编译器不能编译通过,20行会报错。因为定义数组array,需要知道数组的大小,而数组的大小A+B是由两个只读变量相加得到的。两个变量相加的结果需要到运行时才知道,因此编译器不乐意了,编译器根本不知道数组大小,所以直接报错。
    • C++编译器直接编译通过。因为数组大小是由两个真正意义上的常量A和B来完成的。这时候编译器编译到这个地方,显然知道数组的大小是3。

    3.2 C++中的const与宏定义

    C++中的const常量类似于宏定义:
    const int c = 5;#define c 5

    C++中的const常量与宏定义不同

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

    这是test.cpp代码:

    // test.cpp
    #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;
    }
    

    用g++编译器运行程序结果如下:

    [root@bogon Desktop]# g++ test.cpp
    test.cpp: In function ‘void g()’:
    test.cpp:13: error: ‘b’ was not declared in this scope
    

    宏没有作用域和类型的概念,但是const常量有作用域和类型的概念。两者的本质不一样。

    4.小结

    • 与C语言不同,C++中的const不是只读変量
    • C++中的const是一个真正意义上的常量
    • C++编译器可能会为const常量分配空间
    • C++完全兼容C语言中const常量的语法特性
  • 相关阅读:
    题解 P3842 【[TJOI2007]线段】
    题解 CF1366A 【Shovels and Swords】
    题解 CF1391D
    题解 CF1374B 【Multiply by 2, divide by 6】
    CSP-J2020爆零记
    YbtOJ20025 放置石子
    YbtOJ20001 立方数差
    [仅供参考]W-RB的码风及要求
    [敲黑板]CSP考试策略
    [水沝淼㵘]向量水解
  • 原文地址:https://www.cnblogs.com/PyLearn/p/10066656.html
Copyright © 2011-2022 走看看