D 中的枚举与不可变
D 2.0有什么区别
enum i = 2;
enum s = "Hello";
D 2.0和
immutable i = 2;
immutable s = "Hello";
?
What's the difference between
enum i = 2;
enum s = "Hello";
and
immutable i = 2;
immutable s = "Hello";
in D 2.0?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
enum
是用户定义的类型,而不是变量。enum e = 2;
是一个像这样的简写
enum : int { e = 2 }
(即匿名具有一个成员
e
的枚举),请参阅文档。根据定义,匿名枚举的所有成员都被放入当前
范围。因此,
e
是放置在当前作用域中的类型成员,其行为在当前作用域中就像文字。
另一方面,
immutable i = 2;
实际上创建了一个 int 类型的变量i
。这种差异会带来几个后果:
enum e
将没有内存位置和地址(没有左值),因为类型及其成员都没有地址。即你不能做某事
就像
auto ptr = &e;
(就像你不能做auto ptr = &2;
)。不可变
另一方面,i 是一个普通变量(只是不可变)。
不可变变量可以在编译时或运行时初始化,
而类型(及其定义该类型的所有成员)必须已知
编译时间。
e
替换为2
。对于我
它通常必须创建一个内存位置(尽管优化编译器
有时也许可以避免这种情况)。为此,期间的工作量
enum
的编译预计会稍微低一些,并且二进制稍微小一些。
enum uint[2] E = [0, 1];
和immutable uint[2] I = [0, 1];
对enum
的访问,例如E[0]
,可以比
immutable
数组慢几个数量级,例如I[0]
,特别是当数组
E
和I
变得更大时。之所以如此,是因为对于immutable
数组,它只是一个普通的数组查找,比如全局数组多变的。然而,对于
enum
来说,数组似乎是每隔使用之前的时间,例如在全局
enum
的函数内(不要问我为什么,不过编译器确实好像只是简单的替换了外观
也具有本例中的值)。我从未尝试过,但我猜想
这同样适用于
enum
字符串和其他重要类型。总结一下:当我使用编译时常量时,我通常采用
enum
除非这些常量是数组,或者由于其他原因我需要一个内存位置。
An
enum
is a user-defined type, not a variable.enum e = 2;
is ashort-hand for something like this
enum : int { e = 2 }
(i.e. an anonymousenum with one member
e
), see the documentation.By definition, all members of an anonymous enum are placed into the current
scope. So,
e
is a type member placed into the current scope, where it behaveslike a literal.
immutable i = 2;
on the other hand actually creates a variablei
of type int.This difference has a couple of consequences:
enum e
will have no memory location and no address (is no lvalue), sinceneither a type nor its members have an address. I.e. you cannot do something
like
auto ptr = &e;
(just like you cannot doauto ptr = &2;
).immutable
on the other hand is a normal variable (just immutable).i
immutable variables can be initialized at compile time or at run-time,
whereas a type (with all its members defining the type) must be known at
compile time.
e
with2
. Fori
itusually has to create a memory location (although an optimizing compiler
might be able to avoid this sometimes). For this reason, the workload during
compilation for an
enum
might be expected to be somewhat lower, and thebinary somewhat smaller.
enum uint[2] E = [0, 1];
andimmutable uint[2] I = [0, 1];
the access to theenum
, e.g.E[0]
, canbe orders of magnitude slower than for the
immutable
array, e.g.I[0]
,especially as the arrays
E
andI
get bigger. This is so because for animmutable
array, it is just a normal array lookup to, say, a globalvariable. For the
enum
however it looks like the array gets created everytime before it gets used, e.g. inside a function for a global
enum
(don'task me, why, but the compiler really seems to simply replace the appearance
with the value in this case, too). I have never tried but would guess that
the same applies to
enum
strings and other non-trivial types.To sum up: when I use compile-time constants, I usually take
enum
unlessthose constants are arrays or I need a memory location for some other reason.
枚举总是在编译时初始化。因此,它们必须被赋予可以通过CTFE(编译时函数求值)创建的值。
不可变变量可以在运行时初始化。如果不可变变量具有全局生命周期(因此它是模块变量或静态类或静态局部变量),那么它必须在编译时或在运行时使用静态构造函数进行初始化(尽管静态局部变量不能被分配一个静态构造函数)。如果不可变变量是非静态局部变量,则它在运行时初始化(尽管如果该值是常量,则编译器可能会优化它并在编译时初始化它)。因此,与枚举不同,您可以在运行时创建不可变的局部变量。
编辑:我忘记的另一种情况:不可变成员变量必须直接使用 CTFE 初始化或使用不可变构造函数初始化。如果不可变成员变量直接使用 CTFE 初始化,那么显然这是在编译时完成的,而在不可变构造函数中初始化它是在运行时完成的。
enums are always initialized at compile time. So, they must be assigned values which can be created via CTFE (Compile Time Function Evaluation).
immutable variables can be initialized at runtime. If an immutable variable has a global lifetime (so it's a module variables or a static class or a static local variable), then it must be either be initialized at compile time or at runtime with a static constructor (though static local variables can't be assigned with a static constructor). If an immutable variable is a non-static local variable, then it's initialized at runtime (though if the value is a constant, then the compiler might optimize it and initialize it at compile time). So, you can create immutable local variables at runtime, unlike enums.
EDIT: One other case I forgot: immutable member variables must either be initialized directly with CTFE or initialized with an immutable constructor. If an immutable member varible is initialized directly with CTFE, then obviously that's done at compile time, whereas initializing it in an immutable constructor is done at runtime.