D语言中的const与enum的区别

7
请看来自此处底部的引用内容。(我相信关于const的评论同样适用于invariant

枚举与常量不同之处在于,它们不会在最终输出的对象/库/可执行文件中占用任何空间,而常量会。

因此,显然value1会使可执行文件膨胀,而value2则被视为字面值,不会出现在对象文件中。
const int value1 = 0xBAD;
enum int value2 = 42;

在 C++ 中,我一直认为这是出于遗留原因和旧编译器不能优化常量的原因。但如果 D 语言仍然如此,那么其背后必定有更深层次的原因。有人知道吗?

5个回答

4
与C++中的枚举一样,D语言中的枚举似乎是一个“保留整数字面量”(编辑:令人惊奇的是,D2甚至支持浮点数和字符串)。它的枚举值没有位置。它们只是没有身份的值而已。
在D2中放置enum是新的。它首先定义了一个新变量。它不是左值(因此您也不能取其地址)。
enum int a = 10; // new in D2

就像

enum : int { a = 10 }

如果我对D语言的知识能够信任,那么在这里的a不是一个左值(没有位置且无法取其地址)。然而,一个常量一个地址。如果你有一个全局(不确定这是否是正确的D术语)的常量变量,编译器通常不能将其优化掉,因为它不知道哪些模块可以访问该变量或者可能会取其地址。因此,它必须为其分配存储空间。
我认为,如果你有一个局部常量,编译器仍然可以像在C++中一样将其优化掉,因为编译器通过查看其作用域来确定是否有人感兴趣其地址或者所有人都只需取其值。

4

您的实际问题是:为什么在D语言中,枚举/常量与C++中相同,似乎没有得到答案。遗憾的是,这种选择没有任何好的理由。我认为这只是C++中无意之间产生的一种模式,成为了事实上的模式。在D语言中需要相同的模式,Walter Bright决定应该像C++一样做,以便那些来自那里的人会认识该怎么做...事实上,在这个IMHO非常愚蠢的决定之前,关键字“manifest”被用于此用例而不是枚举。


2
很不幸,“枚举”意味着显式常量。然而,D语言只会更改明确有问题的内容,其他一切都遵循Algol语言的既定规范。我相信,如果你真的全力以赴,你可以找到许多奇怪的关键字和语法,这些关键字和语法可能做得更好,例如赋值/相等、返回值在函数名之前列出、结构/聚合等。 - deft_code

3

我认为一个好的编译器/链接器仍然应该删除常量。只是使用枚举,它在规范中实际上是有保证的。主要的区别是语义问题。(还要记住2.0版本还没有完成)


1
但这个愿望假定编译器始终具有所有相关源代码。 - larsivi
如果您想让第三方库访问该const变量怎么办?如果整个类实例都被设置为const,又该怎么办? - Marenz
请注意,我说的是“编译器/链接器”。此外,D语言必须能够在编译时看到变量的值(用于常量折叠和其他操作),因此在物理上存储它甚至更没有意义——任何需要它的情况下都需要源代码。 (我不知道是否有任何编译器会内部反汇编先前运行的目标代码) - FeepingCreature

2
< p >据我所知,< code >枚举在语法上支持单个清单常量的真正目的是D模板大师Don Clugston正在使用一些疯狂的模板。他因为编译器不断为const变量创建内部数据结构而遇到了长时间的构建时间、荒谬的编译器内存使用等问题。与枚举相比,const/immutable变量的一个关键点是它们是lvalue,并且可以获取其地址。这意味着编译器有一些额外的开销。通常情况下这并不重要,但当你在执行非常复杂的编译时元程序时,即使const变量被优化掉,这仍然是编译时间的重要开销。


1

听起来枚举值将在表达式中“内联”使用,而const实际上会占用存储空间,并且引用它的任何表达式都将从内存存储中加载该值。

这听起来类似于C#中const vs. readonly之间的区别。前者是编译时常量,后者是运行时常量。这肯定会影响程序集的版本控制(因为引用readonly的程序集将在编译时接收到一个副本,并且如果引用的程序集使用不同的值重新构建,则不会更改该值)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接