进化后的 const

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进化后的 const相关的知识,希望对你有一定的参考价值。

        我们之前说过在 C 语言中:const 修饰的变量是只读的,其本质还是变量;它修饰的局部变量在栈上分配空间,修饰的全局变量在只读存储区分配空间;const 只在编译期有效,在运行期无用;const 修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边而已。

        C 语言中的 const 使得变量具有只读属性,所以它在 C 语言中不能定义真正意义上的常量!在 C 语言中,能定义常量的只有 enum(枚举)啦。但是 C++ 在 C 语言的基础上对 const 进行了进化处理:当碰见 const 声明时在符号表中放入常量;编译过程中若发现使用常量则直接以符号表中的值替换;编译过程中若发现下述情况则给对应的常量分配存储空间:a> 对 const 常量使用了 extern,b> 对 const 常量使用 & 操作符。符号表是编译器中的一种数据结构。C++ 编译器虽然可能为 const 常量分配空间,但不会使用其存储空间中的值。那为什么还有这样做呢?是为了兼容 C 语言的特性!

        下来我们以示例代码为例进行分析

#include <stdio.h>

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

        我们先在 gcc 编译器编译下,应该是两个都打印 5。我们看看编译结果

技术分享图片

        结果如我们所分析的那样,因为 c 虽然是由 const 修饰的,但其本质还是变量,所以我们可以通过指针来修改它的值。下来我们用 g++ 编译器编译下看看结果会一样吗?

技术分享图片

        我们看到 c 为 0,*p 为 5。这就符合了我们之前讲的,在 C++ 中,它会将由 const 修饰的变量放入符号表中,在后面见到它会直接在符号表中进行查找,但是 *p 确实改变了,所以 *p 为 5。我们用下面这张图来具体说明

技术分享图片

        那么在 C 语言中的 const 变量是只读变量,会分配存储空间;在 C++ 中,const 就为常量了,可能会为其分配空间:a> 当 const 常量为全局,并且需要在其他文件中使用时;b> 当使用 & 操作符对 const 常量取地址;

        在 C++ 中,const 常量有点就类似于宏定义了,但是它们是不一样的。const 常量是由编译器处理,编译器对 const 常量进行类型检查和作用域检查;宏定义由预处理器处理,是单纯的文本替换,并没有作用域的限制。下来我们以代码为例进行分析

#include <stdio.h>

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

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

        我么看到在 main 函数定义了两个 const 修饰的变量,我们用它们的和来定义数组的大小。在 C 语言中肯定是不行的,因为它们在本质上是变量,数组大小怎么可能用变量定义。但是在 C++ 中,它们就已经被放入了符号表,就为常量了。我们来看看分别用 gcc 和 g++ 编译器编译下是什么结果技术分享图片

        我们看到用 gcc 编译器编译直接报错,但是我们用 g++ 编译器编译则通过,并且成功运行。我们再来看看 C++ 中的 const 常量和宏定义有什么区别,我们在 f() 中分别定义了宏 a 和 const b,在 g() 中进行打印。我们之前说过,宏定义是没有作用域的限制的,而 const 常量则是由作用域的,所以 b 的作用域仅为 f 函数,在 g 中打印是会出错的。我们去掉 main 函数中的第 28 行的注释,看看是什么结果

技术分享图片

        我们看到它报的是 b 没有定义。我们注释掉第 12 行,再次编译

技术分享图片

        通过实验,我们更加清晰的认识到宏定义和 const 常量的区别。通过对 C 和 C++ 中的 const 的学习,总结如下:1、与 C 语言不同,C++ 中的 const 不只是只读变量;2、C++ 中的 const 是一个真正意义上的常量;3、C++ 编译器可能会为 const 常量分配空间;4、C++ 完全兼容 C 语言中的 const 常量的语法特性。


        欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083

以上是关于进化后的 const的主要内容,如果未能解决你的问题,请参考以下文章

进化后的 const

jacript var let const 区别

Sleep() 方法后的代码片段没有被执行

病毒进化树构建

vue2.0 代码功能片段

结合两个代码片段?将用户输入的 Youtube url 转换为嵌入 url,然后将 iframe src 替换为转换后的 url