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(2enum
这样的实例化总是在编译时进行求值(并且在编译时无法求值时抛出编译错误)
因此,串接是在编译时完成的,不可变版本存储在代码中并在运行时引用检查字符串是否在编译时串接的一种方法是编译代码并检查目标文件。假设您的文件名为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........