2011-04-28 62 views
1

當我們聲明const變量時,它在Bruce eckel書中說,發生常量摺疊意味着內存不會分配給變量。在C++中聲明爲const的數據時發生了什麼

當我們聲明變量爲const時會發生什麼?

  1. 編譯器如何自由優化const變量?
  2. 內存是否爲const變量總是被分配的,在哪些情況下可能不會?
+0

你需要更精確地知道你想知道什麼。 – James 2011-04-28 08:35:12

+0

我想要什麼是內存摺疊和爲什麼內存摺疊是爲const變量完成的。 – 2011-04-28 08:36:56

+0

看起來像「記憶摺疊」是埃克爾發明的一個術語(如果OP是正確引用的話) - 谷歌爲它顯示沒有任何相關。 – 2011-04-28 08:46:38

回答

1

我發現歸因於布魯斯·埃克爾一個PDF以下報價:

const int的BUFSIZE = 100;您可以在編譯器 必須知道編譯時的值的任何地方使用 bufsize。 編譯器可以使用bufsize至 執行常量摺疊,這意味着 編譯器會在編譯時執行必要的計算 ,將複雜的 常量表達式減少爲一個簡單的表達式 。這一點尤其 重要數組的定義:

假設你的意思是「常量摺疊」,而不是「記憶摺疊」,他的意思是:

const int i = 10; 
const int j = 20; 
int k = i + j; 

記憶並不一定是分配給ij如果編譯器可以證明這是他們唯一使用它們的時間。在這種情況下,它可以用int k = 30;代替全部三行因爲變量被標記爲const,所以編譯器可以自由地假定它們的值永遠不會改變,並且它足夠聰明,可以提前爲你做添加,而不是等待運行時。

對於它的價值,如果你仍然在學習這門語言,我不會太擔心這個。它的一個實現細節;你通常可以指望它發生,但最終的結果是一樣的。編寫有意義的代碼,根據需要使用const以防止錯誤[而不是作爲一種節省內存的方式],並且如果編譯器能夠爲您吐出一些特別的東西,那麼一切都會更好。

-----------原來的答覆如下,因爲它是一種相關主題

沒有直接引用,我的猜測是,他指的是這樣的:

//in file 1: 
const char* string1 = "Hello world!"; 
//in file 2: 
const char* string2 = "Hello world!"; 
//in file 3: 
const char* string3 = "world!"; 

在某些情況下,編譯器/鏈接器能夠發現string1string2都指向相同的字符串。所以它不必創建兩個包含相同數據的單獨字符串對象,並且最終成功。一個更聰明的設置可能會注意到string3是前兩個的子字符串,最後是assert(string3 == string1+6)。在可執行文件的實際數據中,最終只有一個字符串,即使在代碼中有三個字符串。

在C++中,它們並不重要,因爲它們是const,因爲您不能將非const char*分配給字符串文字。但總的來說,如果三個字符串中的任何一個被允許修改它們指向的內存,那麼替換將是無效的。用戶可能不希望*string1 = '5'更改*string2,所以在這種情況下三個字符串不能被壓縮。

+0

正確dennis它的常量摺疊,正如你所說的「如果存儲器不需要爲i和j分配,那麼值將被存儲在那裏。你認爲這些值存儲在符號表中。因爲每個編譯單元都有一個符號table.I不知道 – 2011-04-28 09:38:08

+0

@Chris:他們會在編譯時得到符號表中的條目,是的,只是標記爲常量。編譯完成後,在這樣的情況下,它們可能會消失,值「50」直接出現在說明中。其他時候,新的值將與可執行文件存儲的任何其他數據一起插入。 – 2011-04-28 12:36:55

0

「是指內存不分配給變量。」

你就錯了。如果它是一個變量(無論是const還是非const),它應該駐留在內存的某個部分。

當你聲明一個變量爲const表示該變量不能在其生命期中被修改。

const int num = 10 ; 

num = 20 ; // Error : num cannot be modified. It is just a read only variable. 

int var = 10 ; 
var = 20 ; // var is a modifiable integer variable. 
+0

不完全正確,你忘了'const_cast'關鍵字... – Simone 2011-04-28 08:37:58

+0

對於函數範圍或文件靜態常量變量,編譯器知道何時編譯CU是否獲取變量的地址,或者只是使用了它的價值。如果它的地址從未被採用,那麼它可以用變量值替換const變量的使用;至少對於簡單的類型。 – James 2011-04-28 08:39:13

+0

@Simone - 你是對的。應該提到它。謝謝。 – Mahesh 2011-04-28 08:39:14

3

編譯器可以自由地優化常量變量(和其他任何東西),只要你不能區分程序的作用。

例如:

const int three = 3; 
const int four = 4; 

int f() { return three * four; } 

在這裏,編譯器就可以省略的變量分配存儲空間,並可能會產生相同的代碼,就好像它是寫return 12;

但是,如果你拿了地址three,或綁定對它的引用,或者聲明爲extern,那麼編譯器可能會被迫爲它分配內存。

+0

我同意你Alan,但是三和四的值被存儲在哪裏。你的意思是他們存儲在符號表中嗎? – 2011-04-28 09:39:31

+0

如果在運行時不需要它們,它們可能不會存儲在二進制文件中 - 例如,如果它們標記爲靜態文件並且只用於上述表達式中。即使它們在運行時需要,它們也可能直接存儲在處理器指令中,而不是存儲在.DATA部分中。 – gnud 2011-04-28 09:48:48

+0

編譯器需要知道這些值,所以是的,他們必須以某種方式通過符號表訪問。在運行時不需要存儲這些值。 – 2011-04-28 10:17:15

相關問題