我一直认为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的这些问题,以后在开发过程中可能会碰到坑。

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

  1. 理解es6中的const与“不变”

    const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动. 效果 对于简单类型的数据(数值.字符串.布尔值),值就保存在变量指向的那个内存地址,因此等同于常量. 对于复合类型 ...

  2. 深入理解C++中的mutable,using,decltype等关键字

    深入理解C++中的mutable关键字 mutable的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词. 在C++中,mutable也是为了突破const的限制而设 ...

  3. 深入理解C++中的mutable关键字

      mutalbe的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词. 在C++中,mutable也是为了突破const的限制而设置的.被mutable修饰的变量,将 ...

  4. 深度理解js中var let const 区别

    首先要理解js中作用域的概念 作用域:指的是一个变量的作用范围 1.全局作用域 直接写在script中的js代码,在js中,万物皆对象,都在全局作用域,全局作用域在页面打开时创建,在全局作用域中有一个 ...

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

    ES6之let(理解闭包)和const命令 最近做项目的过程中,使用到了ES6,因为之前很少接触,所以使用起来还不够熟悉.因此购买了阮一峰老师的ES6标准入门,在此感谢阮一峰老师的著作. 我们知道,E ...

  6. 简单理解ECMAScript2015中的箭头函数新特性

    箭头函数(Arrow functions),是ECMAScript2015中新加的特性,它的产生,主要有以下两个原因:一是使得函数表达式(匿名函数)有更简洁的语法,二是它拥有词法作用域的this值,也 ...

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

    声明:本博客为原创博客,未经同意,不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(原文链接为http://blog.csdn.net/bettarwang/article/det ...

  8. 深入理解C++中的explicitkeyword

    深入理解C++中的explicitkeyword kezunhai@gmail.com http://blog.csdn.net/kezunhai C++中的explicitkeyword仅仅能用于修 ...

  9. C++中关于const的思考

    在学习C++的过程中,经常被什么时候使用const.为什么使用const以及怎么使用const关键字这样的问题所困扰,以下是我对const的使用总结. 1.值替代 使用#define的确单缺点,第一: ...

随机推荐

  1. Python 模块化 from .. import 语句介绍 (二)

    from语句 例一. from pathlib import Path,PosixPath print(dir()) print(Path) print(PosixPath) 运行结果: ['Path ...

  2. 如何寫一個自定義控件/vs2010生成Dll文件并引用dll(C#)

    1.最簡單的例子 首先你先新建->項目->類庫.然後右鍵項目.添加一個用戶控件.設置其用戶控件繼承button. egg: namespace ClassLibrary1{    publ ...

  3. 利用JDK自带工具keyTool生成安全证书

    前言:说一下最近做的工作,主要利用iText给网页中生成好的html报表转化为pdf格式的文件,并且在其中加入水印,数字签名等等,这部分主要介绍安全证书的目的就是为了做数字签名部分用的. 下面利用jd ...

  4. PAT——1035. 插入与归并

    根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...

  5. 为什么我不再用 .NET 框架(网摘)

    觉得好就拿过来收藏了,保留出处链接-凌风 2017年08月23日 14:51:32 hisense_大致若愚 阅读数:9355 .NET平台很棒.真的很棒.直到它不再那么棒.我为什么不再用.NET?简 ...

  6. C++笔记016:const 基础

    原创笔记,转载请注明出处! 点击[关注],关注也是一种美德~ 笔记十六关于const关键字,在C语言和C++中const的表现是不同的. 先看一下const基础知识. 对const的初级理解:cons ...

  7. js数组定义和方法 (包含ES5新增数组方法)

    数组Array 1. 数组定义 一系列数据的集合成为数组.数组的元素可以为任何类型的数据(包括数组,函数等),每个元素之间用逗号隔开,数组格式:[1,2,3]. 2. 数组创建方式 (1) 字面量方法 ...

  8. less的编译

    less其实也文本类型,跟txt的性质差不多 less有自己语法(变量,函数,作用域.Mixin混入),使css样式更加方便,有逻辑性,提高可维护性,减少重复性代码的冗余. 把less编译成css文件 ...

  9. Python学习 :多线程 --- 锁

    多线程 什么是锁? - 锁通常被用来实现对共享资源的同步访问. - 为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线 ...

  10. LSTM网络应用于DGA域名识别--文献翻译--更新中

    原文献名称 Predicting Domain Generation Algorithms with Long Short-Term Memory Networks原文作者 Jonathan Wood ...