關鍵字 mutable和volatile

2021-08-02 22:55:06 字數 3461 閱讀 1207

(1)mutable

在c++中,mutable是為了突破const的限制而設定的。被mutable修飾的變數,將永遠處於可變的狀態,即使在乙個const函式中,甚至結構體變數或者類物件為const,其mutable成員也可以被修改。

1.structst  

2.  

3.  ;  

10. 

11.constst st=;  

12. 

13.  st.a=11;//

編譯錯誤

14. 

15.  st.b=22;//允許

mutable在類中只能夠修飾非靜態資料成員。mutable 資料成員的使用看上去像是騙術,因為它能夠使const函式修改物件的資料成員。然而,明智地使用 mutable 關鍵字可以提高**質量,因為它能夠讓你向使用者隱藏實現細節,而無須使用不確定的東西。我們知道,如果類的成員函式不會改變物件的狀態,那麼這個成員函式一般會宣告成const的。但是,有些時候,我們需要在const的函式裡面修改一些跟類狀態無關的資料成員,那麼這個資料成員就應該被mutalbe來修飾。

1.classst  

2.  

3.  ;  

14. 

15.  st::show()  

16. 

17.   

const承諾的是一旦某個變數被其修飾,那麼只要不使用強制轉換(const_cast),在任何情況下該變數的值都不會被改變,無論有意還是無意,而被const修飾的函式也一樣,一旦某個函式被const修飾,那麼它便不能直接或間接改變任何函式體以外的變數的值,即使是呼叫乙個可能造成這種改變的函式都不行。這種承諾在語法上也作出嚴格的保證,任何可能違反這種承諾的行為都會被編譯器檢查出來。

mutable的承諾是如果某個變數被其修飾,那麼這個變數將永遠處於可變的狀態,即使在乙個const函式中。這與const形成了乙個對稱的定義,乙個永遠不變,而另外乙個是永遠可變。

看乙個變數或函式是否應該是const,只需看它是否應該是constant或invariant,而看乙個變數是否應該是mutable,也只需看它是否是forevermutative。

這裡出現了令人糾結的3個問題:

1、為什麼要保護類的成員變數不被修改? 2

、為什麼用

const

保護了成員變數,還要再定義乙個

mutable

關鍵字來突破

const

的封鎖線? 3

、到底有沒有必要使用

const

和mutable

這兩個關鍵字?

保護類的成員變數不在成員函式中被修改,是為了保證模型的邏輯正確,通過用const關鍵字來避免在函式中錯誤的修改了類物件的狀態。並且在所有使用該成員函式的地方都可以更準確的**到使用該成員函式的帶來的影響。而mutable則是為了能突破const的封鎖線,讓類的一些次要的或者是輔助性的成員變數隨時可以被更改。沒有使用

const

和mutable

關鍵字當然沒有錯,

const

和mutable

關鍵字只是給了建模工具更多的設計約束和設計靈活性,而且程式設計師也可以把更多的邏輯檢查問題交給編譯器和建模工具去做,從而減輕程式設計師的負擔。

象const一樣,volatile是乙個型別修飾符。volatile修飾的資料,編譯器不可對其進行執行期寄存於暫存器的優化。這種特性,是為了滿足多執行緒同步、中斷、硬體程式設計等特殊需要。遇到這個關鍵字宣告的變數,編譯器對訪問該變數的**就不再進行優化,從而可以提供對特殊位址的直接訪問。

volatile原意是「易變的」,但這種解釋簡直有點誤導人,應該解釋為「直接訪問原始記憶體位址」比較合適。「易變」是相對與普通變數而言其值存在編譯器(優化功能)未知的改變情況(即不是通過執行**賦值改變其值的情況),而是因外在因素引起的,如多執行緒,中斷等。編譯器進行優化時,它有時會取一些值的時候,直接從暫存器裡進行訪問,而不是從記憶體中獲取,這種優化在單執行緒的程式中沒有問題,但到了多執行緒程式中,由於多個執行緒是併發執行的,就有可能乙個執行緒把某個公共的變數已經改變了,這時其餘執行緒中暫存器的值已經過時,但這個執行緒本身還不知道,以為沒有改變,仍從暫存器裡獲取,就導致程式執行會出現未定義的行為。並不是因為用volatile修飾了的變數就是「易變」了,假如沒有外因,即使用volatile定義,它也不會變化。而加了

volatile

一般說來,volatile用在如下的幾個地方:

1、中斷服務程式中修改的供其它程式檢測的變數需要加

volatile;

2、多工環境下各任務間共享的標誌應該加

volatile;

3、儲存器對映的硬體暫存器通常也要加

volatile

說明,因為每次對它的讀寫都可能有不同意義;

使用該關鍵字的例子如下:

1.volatile

inti=10;  

2.  

3.inta = i;  

4.  

5.  ...  

6.  

7.  

//其他**,並未明確告訴編譯器,對

i進行過操作

8.  

9.intb = i; 

volatile 指出 i是隨時可能發生變化的,每次使用它的時候必須從i的位址中讀取,因而編譯器生成的彙編**會重新從i的位址讀取資料放在b中。而優化做法是,由於編譯器發現兩次從i讀資料的**之間的**沒有對i進行過操作,它會自動把上次讀的資料(即10)放在b中,而不是重新從i裡面讀。這樣以來,如果i是乙個暫存器變數或者表示乙個埠資料就容易出錯,所以說volatile可以保證對特殊位址的直接訪問。

1.  //addr為volatile變數  

2.  

addr=0x57;   

3.  

addr=0x58;  

如果上述兩條語句是對外部硬體執行不同的操作,那麼編譯器就不能像對待普通的程式那樣對上述語句進行優化只認為「addr=0x58;」而忽略第一條語句(即只產生一條機器**),此時編譯器會逐一的進行編譯並產生相應的機器**(兩條)。

volatile總是與優化有關,編譯器有一種技術叫做資料流分析,分析程式中的變數在**賦值、在**使用、在**失效,分析結果可以用於常量合併,常量傳播等優化,進一步可以死**消除。但有時這些優化不是程式所需要的,這時可以用volatile關鍵字禁止做這些優化,它有下面的作用:

1、不會在兩個操作之間把volatile變數快取在暫存器中。在多工、中斷等環境下,變數可能被其他的程式改變,編譯器自己無法知道,volatile就是告訴編譯器這種情況。

2、不做常量合併、常量傳播等優化,所以像下面的**,if的條件不會當作無條件真。

1.volatile

inti = 1;   

2.if(i > 0)  

3.         ...   

關鍵字mutable小議

關鍵字mutable小議 內容 我們知道在用const修飾的類成員函式,這意味著什麼,從effective c 這本書上我們可以了解到,這裡存在兩個流行的概念 bitwise constness or physical constness 和logical constness.bitwise con...

mutable關鍵字解析

c 11引入mutable關鍵字,它是乙個型別修飾符,用來修飾成員變數或者是lambda函式,接下來分布來說明。當mutable用來修飾成員變數時,表明該成員變數屬於物件內部可變狀態,對外不可見。即使在const函式也可改變,不影響外部使用者對此const函式的邏輯語義。比如,基於mutex的執行緒...

volatile關鍵字和mutable關鍵字

如果不用volatile關鍵字會如何?可能會造成乙個後果就是 編譯器發現你多次使用同乙個變數的值,然後它可能會假設這個變數是不變的值,並且把這個變數的值放入暫存器中,方便下一次使用,提高訪問速度。乙個定義為volatile的變數是說這變數可能會被意想不到地改變,這樣,編譯器就不會去假設這個變數的值了...