mutable、volatile的使用

本文转载自http://blog.csdn.net/tht2009/article/details/6920511

       (1)mutable

       在C++中,mutable是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中,甚至结构体变量或者类对象为const,其mutable成员也可以被修改。

struct  ST{int a;mutable int b;};const ST st={1,2};st.a=11;//编译错误st.b=22;//允许



       mutable在类中只能够修饰非静态数据成员。mutable 数据成员的使用看上去像是骗术,因为它能够使const函数修改对象的数据成员。然而,明智地使用 mutable 关键字可以提高代码质量,因为它能够让你向用户隐藏实现细节,而无须使用不确定的东西。我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰。

class  ST{int a;mutable int showCount;void Show()const;…};ST::Show(){…//显示代码a=1;//错误,不能在const成员函数中修改普通变量showCount++;//正确}


 

       const承诺的是一旦某个变量被其修饰,那么只要不使用强制转换(const_cast),在任何情况下该变量的值都不会被改变,无论有意还是无意,而被const修饰的函数也一样,一旦某个函数被const修饰,那么它便不能直接或间接改变任何函数体以外的变量的值,即使是调用一个可能造成这种改变的函数都不行。这种承诺在语法上也作出严格的保证,任何可能违反这种承诺的行为都会被编译器检查出来。

       mutable的承诺是如果某个变量被其修饰,那么这个变量将永远处于可变的状态,即使在一个const函数中。这与const形成了一个对称的定义,一个永远不变,而另外一个是永远可变。

       看一个变量或函数是否应该是const,只需看它是否应该是constant或invariant,而看一个变量是否应该是mutable,也只需看它是否是forever mutative。

       这里出现了令人纠结的3个问题:

       1、为什么要保护类的成员变量不被修改?

       2、为什么用const保护了成员变量,还要再定义一个mutable关键字来突破const的封锁线?

       3、到底有没有必要使用const 和 mutable这两个关键字?

       保护类的成员变量不在成员函数中被修改,是为了保证模型的逻辑正确,通过用const关键字来避免在函数中错误的修改了类对象的状态。并且在所有使用该成员函数的地方都可以更准确的预测到使用该成员函数的带来的影响。而mutable则是为了能突破const的封锁线,让类的一些次要的或者是辅助性的成员变量随时可以被更改。没有使用const和mutable关键字当然没有错,const和mutable关键字只是给了建模工具更多的设计约束和设计灵活性,而且程序员也可以把更多的逻辑检查问题交给编译器和建模工具去做,从而减轻程序员的负担。

(2)volatile

       象const一样,volatile是一个类型修饰符。volatile修饰的数据,编译器不可对其进行执行期寄存于寄存器的优化。这种特性,是为了满足多线程同步、中断、硬件编程等特殊需要。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的直接访问。

       volatile原意是“易变的”,但这种解释简直有点误导人,应该解释为“直接存取原始内存地址”比较合适。“易变”是相对与普通变量而言其值存在编译器(优化功能)未知的改变情况(即不是通过执行代码赋值改变其值的情况),而是因外在因素引起的,如多线程,中断等。编译器进行优化时,它有时会取一些值的时候,直接从寄存器里进行存取,而不是从内存中获取,这种优化在单线程的程序中没有问题,但到了多线程程序中,由于多个线程是并发运行的,就有可能一个线程把某个公共的变量已经改变了,这时其余线程中寄存器的值已经过时,但这个线程本身还不知道,以为没有改变,仍从寄存器里获取,就导致程序运行会出现未定义的行为。并不是因为用volatile修饰了的变量就是“易变”了,假如没有外因,即使用volatile定义,它也不会变化。而加了volatile修饰的变量,编译器将不对其相关代码执行优化,而是生成对应代码直接存取原始内存地址。

       一般说来,volatile用在如下的几个地方:

       1、中断服务程序中修改的供其它程序检测的变量需要加volatile;

       2、多任务环境下各任务间共享的标志应该加volatile;

       3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义;

       使用该关键字的例子如下:

volatile int i=10;int a = i;...//其他代码,并未明确告诉编译器,对i进行过操作int b = i;


 

       volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据(即10)放在b中,而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的直接访问。

//addr为volatile变量
addr=0x57; 
addr=0x58;

       如果上述两条语句是对外部硬件执行不同的操作,那么编译器就不能像对待普通的程序那样对上述语句进行优化只认为“addr=0x58;”而忽略第一条语句(即只产生一条机器代码),此时编译器会逐一的进行编译并产生相应的机器代码(两条)。

       volatile总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以死代码消除。但有时这些优化不是程序所需要的,这时可以用volatile关键字禁止做这些优化,它有下面的作用:
  1、不会在两个操作之间把volatile变量缓存在寄存器中。在多任务、中断等环境下,变量可能被其他的程序改变,编译器自己无法知道,volatile就是告诉编译器这种情况。
  2、不做常量合并、常量传播等优化,所以像下面的代码,if的条件不会当作无条件真。 

volatile int i = 1; if (i > 0)... 


       3、对volatile变量的读写不会被优化掉。如果你对一个变量赋值但后面没用到,编译器常常可以省略那个赋值操作,然而对Memory Mapped IO的处理是不能这样优化的。

 


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/258950.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文本框点击后文字消失总结

1.文本框显示默认文字&#xff1a; <textarea>白鸽男孩</textarea> <textarea>白鸽男孩</textarea>    2.鼠标点击文本框&#xff0c;默认文字消失&#xff1a; <textarea οnfοcus”if(value’白鸽男孩’) {value’ ‘}”>白鸽男孩</text…

[裴礼文数学分析中的典型问题与方法习题参考解答]4.5.8

需要全部的解答, 请 http://www.cnblogs.com/zhangzujin/p/3527416.html 设 $f(x)$ 在 $[a,\infty)$ 上可微; 且 $x\to\infty$ 时, $f(x)$ 单调递增趋于 $\infty$, 则 $$\bex \int_a^\infty \sin f(x)\rd x,\quad \int_a^\infty \cos f(x)\rd x \eex$$ 都收敛. 证明: 由 $$\be…

《PowerShell V3——SQL Server 2012数据库自动化运维权威指南》——2.13 创建视图...

本节书摘来自异步社区出版社《PowerShell V3—SQL Server 2012数据库自动化运维权威指南》一书中的第2章&#xff0c;第2.13节&#xff0c;作者&#xff1a;【加拿大】Donabel Santos&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看。 2.13 创建视图 本方案展…

python刷抖音_用Python生成抖音字符视频!

抖音字符视频在去年火过一段时间。 反正我是始终忘不了那段极乐净土的音乐... 这一次自己也来实现一波&#xff0c;做一个字符视频出来。 主要用到的库有cv2&#xff0c;pillow库。 原视频如下&#xff0c;直接抖音下载的&#xff0c;妥妥的水印。 不过并不影响本次的操作。 / …

变长参数

转载自&#xff1a;http://blog.csdn.net/tht2009/article/details/7019635 变长参数 设计一个参数个数可变、参数类型不定的函数是可能的&#xff0c;最常见的例子是printf函数、scanf函数和高级语言的Format函数。在C/C中&#xff0c;为了通知编译器函数的参数个数和类型可变…

第十七章 我国农业科学技术

农村改革解说&#xff08;专著&#xff09;第十七章 第十七章 我国农业科学技术 1、为什么说科学技术是生产力&#xff1f; 我们说科学技术是生产力&#xff0c;是因为在构成生产力的两个主要因素中&#xff0c;都包含着科学技术在内。 A、生产力中人的因素是同一定的科学技术紧…

《淘宝网开店 拍摄 修图 设计 装修 实战150招》一一1.2 选购镜头时应注意的事项...

本节书摘来自异步社区出版社《淘宝网开店 拍摄 修图 设计 装修 实战150招》一书中的第1章&#xff0c;第1.2节&#xff0c;作者&#xff1a; 葛存山&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看。 1.2 选购镜头时应注意的事项 面对如此之多的镜头&#xf…

OpenCV中的神器Image Watch

Image Watch是在VS2012上使用的一款OpenCV工具&#xff0c;能够实时显示图像和矩阵Mat的内容&#xff0c;跟Matlab很像&#xff0c;方便程序调试&#xff0c;相当好用。跟VS2012配合使用&#xff0c;简直就是一款神器&#xff01;让我一下就爱上它了&#xff01; 下面介绍一些链…

python异步_Python通过Thread实现异步

当long函数耗时较长时&#xff0c;需要程序先向下执行&#xff0c;这就需要异步&#xff0c;改写代码如下&#xff1a; import _thread import time def long(cb): print (long execute) def fun(callback): time.sleep(5) result long end callback(result) _thread.start_ne…

SAM4E单片机之旅——13、LCD之ASF初步

在Atmel Studio 6中&#xff0c;集成了Atmel Software Framework&#xff08;ASF框架&#xff09;。通过它提供的库&#xff0c;可以很快速地完成新的项目。 这次的最终目标使用ASF在LCD上显示出文字“Hello World!”&#xff0c;现阶段目标是点亮LCD的背光&#xff0c;学习目标…

《HTML5与CSS3实战指南》——2.2 基本的HTML5模板

本节书摘来自异步社区《HTML5与CSS3实战指南》一书中的第2章&#xff0c;第2.2节,作者&#xff1a; 【美】Estelle Weyl , Louis Lazaris , Alexis Goldstein 更多章节内容可以访问云栖社区“异步社区”公众号查看。 2.2 基本的HTML5模板 在您学习HTML5和新技术时&#xff0c;您…

c# Message const

typeTMsg packed recordhwnd: HWND; //窗口句柄message: UINT;//消息常量标识符wParam: WPARAM ;// 32位消息的特定附加信息lParam: LPARAM ;// 32位消息的特定附加信息time: DWORD;//消息创建时的时间pt: TPoint; //消息创建时的鼠标位置end ; 消息中有什么&#xff1f;是否觉…

OpenCV坐标体系的初步认识

实验基础本次实验通过一个简短的例子&#xff0c;主要来说明下面4个问题&#xff1a; 1. 坐标体系中的零点坐标为图片的左上角&#xff0c;X轴为图像矩形的上面那条水平线&#xff1b;Y轴为图像矩形左边的那条垂直线。该坐标体系在诸如结构体Mat,Rect,Point中都是适用的。&…

python爬取知乎live_Python爬虫 - 简单抓取百度指数

前言有点忙&#xff0c;没空写东西&#xff0c;这是之前写的&#xff0c;加了些配图而已 这次要爬的网站是百度指数 正文 一、分析 打开网站(百度指数)&#xff0c;呈现出来是这样的 如果搜索的话就需要登陆了&#xff0c;如果没有什么特别频繁的请求的话&#xff0c;直接登陆复…

在Visual Studio上开发Node.js程序

在Visual Studio上开发Node.js程序 原文:在Visual Studio上开发Node.js程序【题外话】 最近准备用Node.js做些东西&#xff0c;于是找找看能否有Visual Studio上的插件以方便开发。结果还真找到了一个&#xff0c;来自微软的Node.js Tools for Visual Studio&#xff08;NTVS&a…

Oracle ASM 翻译系列第十一弹:高级知识 Offline or drop?

Offline or drop? 当一个ASM磁盘不可用时&#xff0c;ASM会把它从磁盘组里移除&#xff0c;对吗&#xff1f;要看情况&#xff0c;通常取决于ASM版本和磁盘组的冗余级别。因为一个external冗余的磁盘组会直接被dismount&#xff0c;所以主要关注normal和high冗余磁盘组的情况。…

net与树莓派的情缘-安装与卸载MySql(五)

安装MySql sudo apt-get install mysql-server 删除 mysql sudo apt-get autoremove --purge mysql-server-5.0sudo apt-get remove mysql-serversudo apt-get autoremove mysql-serversudo apt-get remove mysql-common //这个很重要上面的其实有一些是多余的。 清理残留数据 …

mpls工作原理通俗解释_用这两种方法向最终用户解释NLP模型的工作原理还是不错的...

点击上方关注&#xff0c;All in AI中国上周&#xff0c;我看了一个关于“NLP的实践特性工程”的演讲。主要是关于LIME和SHAP在文本分类可解释性方面是如何工作的。我决定写一篇关于它们的文章&#xff0c;因为它们很有趣、易于使用&#xff0c;而且视觉上很吸引人。所有的机器…

向往2的年代

1. JDBC 对插入大量数据如何处理&#xff1f; 2. JAVA反射的使用&#xff0c;如何获取一个java类的某个方法&#xff1f; 3. 数据库连接池&#xff08;优化&#xff09; 4. 分布式事务管理转载于:https://www.cnblogs.com/dragonflyyi/p/3564843.html

C++ limits头文件的用法(numeric_limits)

初学C的时候&#xff0c;对这个模板很陌生&#xff0c;不知道它到底是做什么用的&#xff0c;今天拿起《C标准程序库》&#xff0c;出现了它的讨论&#xff0c;所以决定好好研究一番。 1. numeric_limits是什么&#xff1f; &#xff08;A&#xff09;《C标准程序库》&#xff…