D 编译时评估

D 编译时评估,d,compile-time,D,Compile Time,如果我写 enum chars = digits ~ uppercase; 字符串是否在编译时连接?我想会的。如果我用字符串文字或CTFE函数替换它,我无法测量任何显著的性能差异(甚至调用它一亿次)。如果我用const替换enum,我会得到不同的结果。有人告诉我这样写效率很低。我认为这是一种方便,我不认为效率低下。(顺便说一句,该行位于递归调用的函数中) 完整代码(转换为具有不同基的数字系统) 导入标准字符串; 串托巴色(长n,内b) 在{ assert(2enum这样的实例化总是在编译时进行

如果我写

enum chars = digits ~ uppercase;
字符串是否在编译时连接?我想会的。如果我用字符串文字或CTFE函数替换它,我无法测量任何显著的性能差异(甚至调用它一亿次)。如果我用const替换enum,我会得到不同的结果。有人告诉我这样写效率很低。我认为这是一种方便,我不认为效率低下。(顺便说一句,该行位于递归调用的函数中)

完整代码(转换为具有不同基的数字系统)

导入标准字符串;
串托巴色(长n,内b)
在{

assert(2
enum
这样的实例化总是在编译时进行求值(并且在编译时无法求值时抛出编译错误)


因此,串接是在编译时完成的,不可变版本存储在代码中并在运行时引用

检查字符串是否在编译时串接的一种方法是编译代码并检查目标文件。假设您的文件名为
test.d

dmd -c test.d
objdump test.o | grep -C3 "012345"
…应该产生类似于:

Contents of section .rodata:
 0000 2d000000 00000000 00000000 00000000  -...............
 0010 01000000 00000000 00000000 00000000  ................
 0020 30313233 34353637 38394142 43444546  0123456789ABCDEF
 0030 4748494a 4b4c4d4e 4f505152 53545556  GHIJKLMNOPQRSTUV
 0040 5758595a 00000000 00000000 00000000  WXYZ............
 0050 24000000 00000000 20000000 00000000  $....... .......
(这在Linux上;在其他平台上,需要使用不同的工具来检查对象文件。)

如果将
enum
更改为
const
string
,则(可能)将不会得到任何输出:将不会有可供
grep
查找的串联字符串

<> p>但是编译器可能在编译时连接字符串,即使不使用代码> EnUM<代码>。
 import std.stdio;

 enum a = "Aaaa";
 enum b = "Bbbb";
 enum c = "Cccc";

 void main() 
 {
   enum   x = a ~ b;
   const  y = b ~ a;
   string z = a ~ c;
   writeln(x, y, z);
 }
现在,编译它并检查对象文件:

% dmd -c test2.d && objdump -s test2.o | egrep "(Aaaa|Bbbb)"
 0000 42626262 41616161 00000000 00000000  BbbbAaaa........
 0020 41616161 43636363 00000000 00000000  AaaaCccc........
 0040 41616161 42626262 00000000 00000000  AaaaBbbb........

我们看到
x
y
z
都是静态文本(将
a
b
c
标记为
const
,而不是
enum
,您可能会看到不同的行为。)因此,虽然
enum
是编译时计算的保证,但是
enum
的缺失并不妨碍编译时计算。

您忘记重置符号字符串(您可以使用
scope(exit)sign=“”;
进行重置),因此
toBase(-10,10)
后跟
toBase(10,10)
将给出相同的结果范围(exit)当当前堆栈帧从堆栈中弹出时执行(如try…finally,但没有额外的缩进)递归不会这样做我会转储该静态,它不是线程安全的,并且(正如所写的)不是异常安全的(这不是代码会遇到的)。避免静态的一种方法是将递归位移到嵌套函数中。@BCS该静态变量的语义与私有全局变量相同,后者在D中位于线程本地存储中(因此是线程安全的)@BCS我尝试了你的建议,效果很好。这是保持状态的更好方法。
 import std.stdio;

 enum a = "Aaaa";
 enum b = "Bbbb";
 enum c = "Cccc";

 void main() 
 {
   enum   x = a ~ b;
   const  y = b ~ a;
   string z = a ~ c;
   writeln(x, y, z);
 }
% dmd -c test2.d && objdump -s test2.o | egrep "(Aaaa|Bbbb)"
 0000 42626262 41616161 00000000 00000000  BbbbAaaa........
 0020 41616161 43636363 00000000 00000000  AaaaCccc........
 0040 41616161 42626262 00000000 00000000  AaaaBbbb........