2011-01-25 125 views
13

是什麼在d 2.0枚舉VS在d

enum i = 2; 
enum s = "Hello"; 

immutable i = 2; 
immutable s = "Hello"; 

的區別一成不變?

回答

23

enum是用戶定義的類型,而不是變量。enum e = 2;是(即匿名 枚舉與一個成員e)類似的東西的 ,請參閱the documentation。根據定義,匿名枚舉的所有成員都被放入當前的 範圍內。所以,e是放置在當前作用域中的類型成員,其行爲 ,如literalimmutable i = 2;實際上創建了一個int類型的變量i

這種差異有幾個後果:

  • enum e將沒有存儲器位置和沒有地址(沒有左值)時,由於既不 一個類型,也不其成員有一個地址。即你不能做 像auto ptr = &e;(就像你不能做auto ptr = &2;)。另一方面,immutable i是一個正常變量(只是不可變的)。
  • As discussed by Jonathan, 不可變的變量可以在編譯時或運行時, 而類型(及其所有成員定義的類型)必須在 編譯時是已知被初始化。
  • 編譯器可以簡單地用2替換e的所有外觀。 i 通常必須創建一個內存位置(儘管優化編譯器 有時可能會避免這種情況)。出於這個原因,編譯enum時 期間的工作負載可能預計略低,而二進制編碼略小。
  • 數組有一個驚人的差異。對於enum uint[2] E = [0, 1];immutable uint[2] I = [0, 1];,訪問enum,例如, E[0],可以 比例如immutable陣列慢幾個數量級。 I[0], 特別是當陣列EI變大。這是因爲對於一個 immutable數組,這只是對全局變量 的常規數組查找。然而,對於enum,看起來像在陣列被使用之前每隔 時間創建陣列,例如,在全球範圍內的功能enum(不要 問我,爲什麼,但編譯器真的好像簡單地用這個值的外觀 取代)。我從來沒有嘗試過,但會猜想 同樣適用於enum字符串和其他非平凡的類型。

綜上所述:當我用編譯時間常數,我通常採取enum除非 那些常量數組或者我需要一些其他的原因,一個內存位置。

8

枚舉總是在編譯時初始化。因此,他們必須爲分配可以通過CTFE(編譯時功能評估)創建的值。

不可變變量可以在運行時初始化。如果一個不可變變量具有全局生存期(因此它是模塊變量或靜態類或靜態局部變量),那麼它必須在編譯時或在運行時使用靜態構造函數初始化(儘管靜態局部變量不能被分配一個靜態構造函數)。如果一個不可變的變量是一個非靜態的局部變量,那麼它在運行時初始化(儘管如果該值是一個常量,那麼編譯器可能會優化它並在編譯時初始化它)。因此,您可以在運行時創建不可變的局部變量,與枚舉不同。

編輯:我忘了另一種情況:不可變的成員變量必須用CTFE直​​接初始化或用不可變的構造函數初始化。如果使用CTFE直​​接初始化一個不可變成員變量,那麼顯然這是在編譯時完成的,而在一個不可變構造函數中初始化它是在運行時完成的。

+0

是的。因爲這不是一個有效的CTFE表達式。您目前不能在CTFE上使用`new`。它還沒有那麼先進。 – 2011-01-25 08:01:34

+0

等等,但是我該如何創建一個不可變的類的實例? – Mehrdad 2011-01-25 08:05:44