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.pswp.cn/news/258950.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/258950.shtml
英文地址,請注明出處:http://en.pswp.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…