2011-01-25 126 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