zoukankan      html  css  js  c++  java
  • 1.const

    在C++中,const 的含义并没有改变,只是对细节进行了一些调整,以下是最主要的两点。

    一.C++中的 const 更像编译阶段的 #define

    先来看下面的两条语句:

    const int m = 10;
    int n = m;

    我们知道,变量是要占用内存的,即使被 const 修饰也不例外。m、n 两个变量占用不同的内存,int n = m;表示将 m 的值赋给 n,这个赋值的过程在C和C++中是有区别的。

    在C语言中,编译器会先到 m 所在的内存取出一份数据,再将这份数据赋给 n;而在C++中,编译器会直接将 10 赋给 n,没有读取内存的过程,和int n = 10;的效果一样。C++ 中的常量更类似于#define命令,是一个值替换的过程,只不过#define是在预处理阶段替换,而常量是在编译阶段替换。

    C++ 对 const 的处理少了读取内存的过程,优点是提高了程序执行效率,缺点是不能反映内存的变化,一旦 const 变量被修改,C++ 就不能取得最新的值。

    有读者提出疑问,const 变量不是禁止被修改吗?对,这种说法没错!不过这只是语法层面上的限制,通过指针仍然可以修改。下面的代码演示了如何通过指针修改 const 变量:

    #include <stdio.h>
    
    int main(){
        const int n = 10;
        int *p = (int*)&n;  //必须强制类型转换
        *p = 99;  //修改const变量的值
        printf("%d
    ", n);
        return 0;
    }

    注意&n得到的指针的类型是const int *,必须强制转换为int *后才能赋给 p,否则类型是不兼容的。

    将代码放到.c文件中,以C语言的方式编译,运行结果为99。再将代码放到.cpp文件中,以C++的方式编译,运行结果就变成了10。这种差异正是由于C和C++对 const 的处理方式不同造成的。

    在C语言中,使用 printf 输出 n 时会到内存中获取 n 的值,这个时候 n 所在内存中的数据已经被修改成了 99,所以输出结果也是 99。而在C++中,printf("%d ", n);语句在编译时就将 n 的值替换成了 10,效果和printf("%d ", 10);一样,不管 n 所在的内存如何变化,都不会影响输出结果。

    当然,这种修改常量的变态代码在实际开发中基本不会出现,本例只是为了说明C和C++对 const 的处理方式的差异:C语言对 const 的处理和普通变量一样,会到内存中读取数据;C++ 对 const 的处理更像是编译时期的#define,是一个值替换的过程。

    二.C++中全局 const 变量的可见范围是当前文件

    我们知道,普通全局变量的作用域是当前文件,但是在其他文件中也是可见的,使用extern声明后就可以使用,下面是多文件编程的演示代码:

    main.c

    #include <stdio.h>
    
    int n = 10;
    void func();
    
    int main(){
        func();
        printf("main: %d
    ", n);
        return 0;
    }

    module.c

    #include <stdio.h>
    
    extern int n;
    
    void func(){
        printf("module: %d
    ", n);
    }

    不管是以C还是C++的方式编译,运行结果都是:

    module: 10
    main: 10

    在C语言中,const 变量和普通变量一样,在其他源文件中也是可见的。修改代码段1,在 n 的定义前面加 const 限制,如下所示:

    const int n = 10;

    修改后的代码仍然能够正确编译,运行结果和上面也是一样的。这说明C语言中的 const 变量在多文件编程时的表现和普通变量一样,除了不能修改,没有其他区别。

      但是如果按照C++的方式编译(将源文件后缀设置为.cpp),修改后的代码就是错误的。这是因为 C++ 对 const 的特性做了调整,C++ 规定,全局 const 变量的作用域仍然是当前文件,但是它在其他文件中是不可见的,这和添加了static关键字的效果类似。虽然在module.c中使用 extern 声明了变量 n,但是在链接时却找不到main.c中的 n。

    由于 C++ 中全局 const 变量的可见范围仅限于当前源文件,所以可以将它放在头文件中,这样即使头文件被包含多次也不会出错,请看下面的例子。

    module.h

    const int n = 10;
    void func();

    module.cpp

    #include <stdio.h>
    #include "module.h"
    
    void func(){
        printf("module: %d
    ", n);
    }

    main.cpp

    #include <stdio.h>
    #include "module.h"
    
    int main(){
        func();
        printf("main: %d
    ", n);
        return 0;
    }

    运行结果:

    module: 10
    main: 10

    C和C++中全局 const 变量的作用域相同,都是当前文件,不同的是它们的可见范围:C语言中 const 全局变量的可见范围是整个程序,在其他文件中使用 extern 声明后就可以使用;而C++中 const 全局变量的可见范围仅限于当前文件,在其他文件中不可见,所以它可以定义在头文件中,多次引入后也不会出错

    如果你使用的是 GCC,那么可以通过添加 extern 关键字来增大 C++ 全局 const 变量的可见范围,如下所示:

    extern const int n = 10;

    这样 n 的可见范围就变成了整个程序,在其他文件中使用 extern 声明后就可以使用了。不过这种方式只适用于 GCC,不适用于 VS/VC。

    总结:

    C++ 中的 const 变量虽然也会占用内存,也能使用&获取得它的地址,但是在使用时却更像编译时期的#define#define也是值替换,可见范围也仅限于当前文件。

    很多C++教程在对比 const 和 #define 的优缺点时提到,#define 定义的常量仅仅是字符串的替换,不会进行类型检查,而 const 定义的常量是有类型的,编译器会进行类型检查,相对来说比 #define 更安全,所以鼓励大家使用 const 代替 #define。

  • 相关阅读:
    JSR303实现数据校验案例
    maven安装和相关配置
    mybatis分页插件使用案例
    分页查询案例
    ssm整合相关配置
    配置文件没有按照maven约定存放解决方法
    git常用命令和基本使用
    mybatis配置二级缓存
    Angular第三方UI组件库------ionic
    Angular路由知识点
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/7053376.html
Copyright © 2011-2022 走看看