修改const變數

2021-07-12 05:29:15 字數 2798 閱讀 4068

宣告:不同於c語言的const變數修改問題(可以通過指標間接修改const變數的值),這裡只討論c++ 裡的const。

c++ const 修飾符,表示常量,即如果以後保證不會修改則宣告為const,否則若要修改,那一開始為什麼還要宣告為const呢?

根據c++標準,對於修改const變數,屬於:未定義行為(指行為不可**的計算機**),這樣一來此行為取決於各種編譯器的具體實現(即不同編譯器可能表現不同)。

故結論就是:

不建議這麼做!

但是,是的,但是,網上論壇、部落格裡均有有關如何修改const變數的方法,其不是依賴於某種具體的編譯器,就是講的欠考慮。

方法是在定義變數的時候加上volatile關鍵字(沒有其他方法了嗎(比如,const_cast ...)? 是的,目前為止,我只知道這種方法是可能的):

[cpp]view plain

copy

print?

const

volatile

int i = 10;  

:關於volatile這裡不細講,詳見:

volatile 關鍵字。考慮到volatile的重要性,後面自己也會寫一篇關於volatile詳解的文章。

為了說明問題,下面在三種編譯器環境下做幾個小實驗

[cpp]view plain

copy

print?

#include 

int main()    

輸出結果:

gdb檢視其彙編**命令:進入gdb,然後輸入:disass main):

可以看出:輸入*pi 和 i 時均是從堆疊(即記憶體)中取數的。

反例:把 volatile關鍵字去掉:

[cpp]view plain

copy

print?

#include 

int main()    

輸出結果:

由此可見:在沒有volatile關鍵字修飾時,const 變數 i 的值時沒有改變的。

運用gdb檢視其彙編**:

注意此時(沒有加volatile修飾符),輸出 變數 i 的值時直接將 0xa(10)值(從符號表中取出的)輸出,即此處編譯器進行了優化,沒有從記憶體中讀。

這就是c++中的常量摺疊:指const變數(即常量)值放在編譯器的符號表中,計算時編譯器直接從表中取值,省去了訪問記憶體的時間,從而達到了優化。

而在此基礎上加上volatile修改符,即告訴編譯器該變數屬於易變的,不要對此句進行優化,每次計算時要去記憶體中取數。

這裡也有個小細節:每種編譯器對volatile修飾符的修飾作用效果不一致,有的就直接「不理會」,如vc++6.0編譯器(下面會講到)。

執行結果與1(g++)一致。

i 的值還是10,沒有改變!這是為什麼呢?不急,先看下其彙編**:

注意:g++ 彙編**的mov指令 與 vc++ 6.0的mov指令不同(傳送方向相反)。

真相大白:雖然定義const變數的同時加上了volatile修飾符,但vc++ 6.0編譯器還是進行了優化措施,輸出 i 時 從編譯器的符號表中取值,直接輸出。

i 的值沒有改變,預期中。其彙編**為:

結果與新增volatile時相同。

即在vc++6.0編譯環境下,在const變數定義時新增volatile修飾符,與不新增效果是一樣的。編譯器都採取了優化(甚至把編譯器優化選項關閉還是如此,有點恐怖...)。

再看下microsoft編譯器家族的高階版本:

i 的值被成功修改了!

i 的值沒有被修改。

故:不建議修改const變數的值,即使修改也要熟悉當前使用的編譯器對於該 未定義行為 是如何解釋的

強行修改const唯讀變數

修改const唯讀變數,只能修改區域性常量,不能修改全域性靜態常量。例如 某函式內部 const int const value 100 int ptr int const value ptr 200 因為在函式內部宣告的 const value,其本質上還是乙個函式內的區域性變數,儲存區在該函式的...

const變數可以修改麼?

遇到了乙個關於const修飾的變數值是否能修改問題,雖然我知道const變數在某些情況下可以通過指向它的指標來間接修改,但是對原理還是很模糊,今天就整理了一下。include int main void 編譯一下,看看出現什麼情況 很遺憾,編譯出錯了。include int main void 編譯...

C 中修改const成員變數

在c 中,被const修飾的變數,表示其不可變。當然c 提供了型別轉換操作符const cast,用來將變數的const屬性臨時性地去掉。如果在乙個類裡面有乙個const成員變數,我們如何在成員函式中修改它呢?class test 那麼我們可以寫這麼乙個函式 void test seta int a...