深入理解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的这些问题,以后在开发过程中可能会碰到坑。

时间: 2024-10-13 22:24:07

深入理解C++中的Const,Mutable以及Volatile的相关文章

理解es6中的const与“不变”

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动. 效果 对于简单类型的数据(数值.字符串.布尔值),值就保存在变量指向的那个内存地址,因此等同于常量. 对于复合类型的数据(主要是对象和数组),变量指向的内存地址,const只能保证这个指针是固定的,不能保证它指向的数据结构是不可变得 'use strict' const obj = {} const arr = [] obj.prop = 123 // 不改动指针 arr.push('Hello') // 只改

深入理解C 中的mutable关键字

mutalbe的中文意思是“可变的,易变的”,跟constant(既C 中的const)是反义词. 在C 中,mutable也是为了突破const的限制而配置的.被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中. 我们知道,假如类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的.但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰. 下面是个小例子: class ClxTest

C++总结:C++中的const和constexpr

C++中的const可用于修饰变量.函数,且在不同的地方有着不同的含义,现总结如下. const的语义 C++中的const的目的是通过编译器来保证对象的常量性,强制编译器将所有可能违背const对象的常量性的操作都视为error. 对象的常量性可以分为两种:物理常量性(即每个bit都不可改变)和逻辑常量性(即对象的表现保持不变).C++中采用的是物理常量性,例如下面的例子: 1 2 3 4 5 6 7 struct A {     int *ptr; }; int k = 5, r = 6;

ES6之let(理解闭包)和const命令

ES6之let(理解闭包)和const命令 最近做项目的过程中,使用到了ES6,因为之前很少接触,所以使用起来还不够熟悉.因此购买了阮一峰老师的ES6标准入门,在此感谢阮一峰老师的著作. 我们知道,ECMAScript 6即ES6是ECMAScript的第五个版本,因为在2015年6月正式发布,所以又成为ECMAScript2015.ES6的主要目的是为了是JS用于编写复杂的大型应用程序,成为企业级的开发语言. 说明:由于有时候我们希望得知es6代码的具体实现原理或者说希望能够转化为es5使用,

C/C++中的const真正的用法

const基础知识(用法.含义.好处) intmain() { constint a; intconst b; constint *c; int* const d; constint * const e ; return0; } Intfunc1(const ) 初级理解:const是定义常量==>const意味着只读 含义: //第一个第二个意思一样代表一个常整形数 //第三个c是一个指向常整形数的指针(所指向的内存数据不能被修改,但是本身可以修改) //第四个d常指针(指针变量不能被修改,但

C与C++中的const

同样,有下面一段代码: 1 #include <iostream> 2 using namespace std; 3 4 int main() 5 { 6 const int i = 0; 7 int *j = (int *) &i; 8 *j = 1; 9 cout<<"i address = 0x"<<hex<<&i<<","<<"j address = 0x&qu

深刻理解Java中final的作用(一):从final的作用剖析String被设计成不可变类的深层原因

声明:本博客为原创博客,未经同意,不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(原文链接为http://blog.csdn.net/bettarwang/article/details/26744661),看代码和提问.讨论都更方便. Java中final的作用主要表如今三方面:修饰变量.修饰方法和修饰类.以下就从这两个方面来解说final的作用.在文末从final及类的设计安全性出发,论述了Java中String为何要被设计成不可变类. 1.final修饰变量 fina

深入理解c++中char*与wchar_t*与string以及wstring之间的相互转换 [转]

本篇文章是对c++中的char*与wchar_t*与string以及wstring之间的相互转换进行了详细的分析介绍,需要的朋友参考下. 1 #ifndef USE_H_ 2 #define USE_H_ 3 4 #include <iostream> 5 #include <windows.h> 6 #include <string> 7 using namespace std; 8 class CUser 9 { 10 public: 11 CUser(); 12

深入理解C++中的explicitkeyword

深入理解C++中的explicitkeyword [email protected] http://blog.csdn.net/kezunhai C++中的explicitkeyword仅仅能用于修饰仅仅有一个參数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相相应的还有一个keyword是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式). 关于explicitkeyword.先看看MSDN上的解释: This keyword is