• 深入解析 const 关键字:指针、参数、返回值和类成员函数


    文章目录

    • const 关键字的理解
    • 一、 修饰普通类型的变量
    • 二、const 修饰指针变量
    • 三、const 作参数传递 和 函数返回值
      • (1)const 修饰函数参数
      • (2)const 修饰函数返回值
    • 四、const修饰类成员函数
    • 结尾

    const 关键字的理解

    const 在 C++ 中是用来修饰内置类型变量自定义对象成员函数返回值函数参数

    C++中, const允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的。如果在编程中确实有某个值保持不变,就应该明确使用const,这样可以获得编译器的帮助。

    使用const有以下好处:

    1. 编译器的静态检查:const 可以让编译器在编译时进行静态检查,确保不会对被声明为 const 的值进行修改。如果尝试修改 const 值,编译器将产生错误或警告。

    2. 代码可读性和维护性:使用 const 可以清晰地表达代码的语义,指出某个值不会被修改。可以提高代码的可读性,并且在维护代码时能够更好地理解和推理代码的含义。

    3. 防止意外修改:通过使用 const,可以避免在代码中意外地修改某个值。特别是当多人协作开发或者代码规模较大时,const 可以起到约束和保护的作用,防止错误的修改。

    4. 优化机会:const 还给编译器提供了一些优化机会,因为编译器知道 const 值不会被修改,可以进行一些相关的优化操作,提高程序的执行效率。

    👇下面我们看const 关键字的使用👇


    一、 修饰普通类型的变量

    观察下面的代码:

    const int a = 10;
    int b = a; // 正常赋值
    a = 20; // 错误,不能给常量赋值
    
    • 1
    • 2
    • 3

    当使用const修饰普通类型的变量a时该变量a会被编译器看成常量,而对常量赋值是违法的。

    当我们写出如下的代码时,会发生一些出乎意料的情况:

    在这里插入图片描述

    我们发现,尽管在监视中a的值为20,但最终输出结果依然为10。

    这是因为 编译器对常量的优化处理将常量 a 存储在只读内存区域,并且优化后的指令可能直接使用常量的值。虽然通过指针修改了数据,但是由于常量 a 是不可修改的,所以它的值仍然保持着 10。


    上面的例子告诉我们,在c++中,尽量不要修改const修饰的变量。
    但我们可以使用volatile 关键字,即下面的写法:

    volatile const int a = 10;
    
    • 1

    当执行上面的代码时,最后结果会输出 “a的值为:20”

    这是因为 volatile 关键字告诉编译器,这个变量的值可能会被意外地修改,因此每次使用这个变量时都要从内存中读取,而不是使用已经存在的寄存器中的值。如果没有使用
    volatile,编译器可能会对这个变量进行一些优化,例如缓存这个变量的值,这样就无法保证每次使用这个变量时都是最新的值。


    二、const 修饰指针变量

    const 修饰指针变量有三种情况:

    ① const 修饰指针指向的内容,则内容为不可变量。
    ② const 修饰指针,指针为不可变量。
    ③ const 同时修饰指针和指针指向的内容,指针和指针指向的内容都为不可变量。


    对于 ①:

    const修饰的常量指针:指针本身是一个常量(既*ptr是不可变的),不能修改指向地址所存储的值,可以修改其指向地址(ptr)。

    // 理解为: const在int*前,所以
    int a = 10, b = 20;
    const int* ptr = &a;
    
    // 修改指向地址所存储的值是不合法的
    *ptr = 20; // 错误,编译器会报错
    
    // 修改指向的地址是合法的
    ptr = &b; // 合法,可以修改指针指向的地址
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    对于②:

    const修饰的指针常量:指针指向的是一个常量,不能通过指针修改所指向地址处的值,但可以修改指针指向的地址。

    int a = 10, b = 20;
    int* const ptr = &a;
    
    // 修改指向地址所存储的值是合法的
    *ptr = 20; // 合法,可以修改指向地址处的值
    
    // 修改指针指向的地址是不合法的
    ptr = &b; // 错误,编译器会报错
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    对于③:

    const同时修饰指针和常量:既不能修改指针本身,也不能通过指针修改所指向地址处的值。

    int a = 10, b = 20;
    const int* const ptr = &a;
    
    // 修改指向地址所存储的值是不合法的
    *ptr = 20; // 错误,编译器会报错
    
    // 修改指针指向的地址是不合法的
    ptr = &b; // 错误,编译器会报错
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    三、const 作参数传递 和 函数返回值

    (1)const 修饰函数参数

    const 修饰 函数参数有以下三种情况:

    1. const修饰的值传递参数
    void func(const int num) {
        // 不能修改num的值
        // ...
    }
    
    • 1
    • 2
    • 3
    • 4

    在这种情况下,形参 num 被声明为常量,函数内部不允许修改它的值。


    1. const修饰的指针传递参数
    void func(const int* ptr) {
        // 不能修改ptr所指向地址处的值
        // ...
    }
    
    • 1
    • 2
    • 3
    • 4

    这里 ptr 是一个指向常量整数的指针,函数内部不能通过指针修改所指向地址处的值,但可以修改指针本身。


    1. const修饰的引用传递参数
    void func(const int& ref) {
        // 不能修改ref所引用的值
        // ...
    }
    
    • 1
    • 2
    • 3
    • 4

    在这种情况下,引用 ref 被声明为常量,函数内部不允许修改它所引用的值。


    (2)const 修饰函数返回值

    const 修饰返回值一样有下面三种情况:

    1. const 修饰返回值为常量:
    const int func() {
        // ...
        return 10;
    }
    
    • 1
    • 2
    • 3
    • 4

    在这种情况下,函数 func() 的返回值被声明为常量,外部代码不能修改返回值。


    1. const 修饰返回指针类型的函数
    int* const func() {
        // ...
        static int num = 10;
        return #
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里 int* const 表示返回值是一个指向整数的常量指针。使用 const 修饰的指针表示指针本身的值是常量,外部代码不能修改指针指向的地址。但可以通过指针修改所指向地址处的值。


    1. const 修饰返回引用类型的函数
    const int& func() {
        // ...
        static int num = 10;
        return num;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这种情况下,返回值是一个指向整数的常量引用。使用 const 修饰的引用表示外部代码不能通过引用修改其所引用的对象。


    四、const修饰类成员函数

    const 修饰类成员函数,其目的是防止成员函数修改被调用对象的值,如果我们不想修改一个调用对象的值,所有的成员函数都应当声明为 const 成员函数。

    注意:const 关键字不能与 static 关键字同时使用,因为 static 关键字修饰静态成员函数,静态成员函数不含有 this 指针,即不能实例化,const 成员函数必须具体到某一实例。


    有下面两种类型:

    1. const 修饰返回引用类型的函数
    class MyClass {
    public:
        void func() const {
            // ...
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这种情况下,成员函数 fnc() 被声明为 const 成员函数。const 成员函数表示该函数不会修改类的成员变量。

    在 const 成员函数中,不能修改非静态成员变量(除非是 mutable 修饰的成员变量),也不能调用非 const 的成员函数。


    1. const 修饰返回值为常量的成员函数
    class MyClass {
    public:
        int getValue() const {
            // ...
            return value;
        }
    private:
        int value;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这种情况下,成员函数 getValue() 被声明为 const 成员函数,并且返回值的类型是 const。这表明该成员函数不会修改类的成员变量并且返回值在外部代码中不能被修改


    结尾

    使用 const 修饰类成员函数可以提供额外的安全性和约束,通过 const 修饰的成员函数,编译器可以对其进行一些优化,在某些情况下还能够调用 const 成员函数来访问 const 对象。同时,也能够帮助开发人员识别和避免意外的修改操作。

  • 相关阅读:
    Leetcode 40. 组合总和 II
    【部署之后的错误排查】远程不能访问
    搭建hadoop+spark完全分布式集群环境
    数字IC验证面试常见的问题汇总,你掌握了几个?
    善于使用二阶思维
    realme手机用什么蓝牙耳机好?2022公认音质最好的蓝牙耳机
    【LeetCode】118. 杨辉三角
    【Ansible】Ansible的Ad-hoc命令执行流程
    前端访问geoserver服务发生跨域的解决办法,以及利用html2canvas下载绘制的地图
    做哪些副业可以日赚一百?对程序员来说简直不要太容易!
  • 原文地址:https://blog.csdn.net/Dreaming_TI/article/details/133646406