• 深入理解C++中的Const,Mutable以及Volatile


    我一直认为const表示一个常量,常量就是一个无法被修改的值,但是没有深入理解const的实现,甚至不知道mutable和volatile的存在,最近在书中看到了这一部分的知识,所以本文将详细解析这几个关键词。

    首先考虑以下几个问题:

    1. const int a和int const a的区别。

    2. const char* s和char *const s的区别。

    3. 下列代码有问题吗?如果有问题应该如何修改?

    class A
    {
    private:
        int a;
        const int fun()
        {
            a = 1;
        }
        int fun() const
        {
            a = 2;
        }
    };

    4. 下列代码一定能达到目的吗?为什么?

    //延时函数
    void delayFun(unsigned int a)
    {
        while (a--)
        {
    
        }
    }

    5.下列代码运行结果是什么?

    const int i = 1;
    int* j = (int*)(&i);
    *j = 2;
    printf("%08x %d %08x %d", &i, i, j, *j);

    针对上述问题解答:

    1. 无区别,表示a是一个const int变量,a无法被修改,并且a可能编译器优化掉(无内存地址)。

    2. const char* s表示s是一个常量字符串的指针,它可以指向不同的常量字符串,例如

    const char* s1 = "abc";
    s1 = "xyz";
    但是字符串内容无法被修改,下列代码出错:
    s1[0]='c';

    char* const s表示一个字符串指针的常量。指向一个唯一的字符串指针,无法后续修改,下列代码出错:

    char* const s1 = "abc";
    s1 = "xyz";

    3. const int fun() 表示一个函数返回值是const int(事实上const int是无意义的),此函数和普通函数没区别。int fun() const表示该函数是常量函数,此函数无法修改类中的成员变量(规定),如果一定要修改类中的成员变量,可以将该成员变量定义为mutable,如下:

    class A
    {
    private:
        mutable int a;
        const int fun()
        {
            a = 1;
        }
        int fun() const
        {
            a = 2;
        }
    };

    4. 代码可能会被优化掉,此函数是一个无效的循环,这类代码会被编译器优化掉,优化后就不存在延时效果了。如果一定要达到延时效果,可以将a定义为volatile。volatile表示此变量可能因为各种原因被修改,告诉编译器不要优化此变量产生的代码(这个一般是底层可能用到,硬件之类的,如果不理解volatile,可能导致代码出现预料之外的情况)。

    5. 这段代码如果是debug模式下可能会被编译器提示出错,因为这里采用了一个强制转换修改了一个常量的值(编译器的理解是,常量是无论如何都无法被修改的,所以高级一点的编译器可能会对此代码报错),但是这段代码从C语言的语言层面上来说是没问题的,C语言里可以将任意指针转换为需要的指针。这段代码在C++中输出:

    0075f8b4 1 0075f8b4 2

    输出地址是一样的,但是值不一样。

    为什么会这样呢?按理说地址一样,他的值肯定也是一样的,原因还是在与编译器的优化(不是编译器的错,const就是一个常量,他就应该是无法被修改的,既然无法被修改,用常量替换没问题)。编译器将所有使用i的地方会用他的值替换,类似与C语言中的#define。这里使用了强制转换强制修改i所在内存的值,但是这个值变化了,不会修改编译器优化后的代码(优化后的代码和和i这个符号都无关了),所以有上述输出。如何修改呢?使用volatile,volatile会要求编译器不要优化该常量,既然不会优化,那么使用i的地方会使用i这个符号而不会优化为常量的值了。如下:

    const volatile int i = 1;
    int* j = (int*)(&i);
    *j = 2;
    printf("%08x %d %08x %d", &i, i, j, *j);

    可以这么理解,const是一个C++为了替换C语言define而产生的关键字,const会留下一些坑。所以就使用mutable和volatile来填补这些坑。如果没搞清const的这些问题,以后在开发过程中可能会碰到坑。

  • 相关阅读:
    Linux常用命令1
    Linux常用命令
    java的接口和抽象类区别
    字符串的全排列
    字符串的全组合
    Mysql范式
    同步 异步 阻塞 非阻塞概念区分
    死锁产生的条件以及解决方法
    Mysql存储引擎MyIsAM和InnoDB区别
    SLES documentation
  • 原文地址:https://www.cnblogs.com/Reyzal/p/7225925.html
Copyright © 2020-2023  润新知