D 为什么模板递归的中间结果在对象文件中?
在D中处理模板递归时,我发现经典阶乘的中间结果仍然在对象文件中。我想它们也在可执行文件中 我可以看到,实际执行的代码只包含值(或指向它的指针),但: 如果中间数据没有被无故保存,难道不应该有一个D 为什么模板递归的中间结果在对象文件中?,d,D,在D中处理模板递归时,我发现经典阶乘的中间结果仍然在对象文件中。我想它们也在可执行文件中 我可以看到,实际执行的代码只包含值(或指向它的指针),但: 如果中间数据没有被无故保存,难道不应该有一个mov语句吗? 代码如下: int main() { static int x = factorial!(5); return x;//factorial!(5); } template factorial(int n) { static if (n == 1) const fact
mov
语句吗?
代码如下:
int main()
{
static int x = factorial!(5);
return x;//factorial!(5);
}
template factorial(int n)
{
static if (n == 1)
const factorial = 1;
else
const factorial = n * factorial!(n-1);
}
这是obj2asm test.o的输出:
(为方便起见:1!=1小时,2!=2小时,3!=6小时,4!=18小时,5!=78小时)
当需要编译时函数执行时,不应该使用模板。只需编写您想要的函数,并在静态上下文中调用它
int main()
{
static int x = factorial(5); // static causes CTFE
return x;
}
int factorial(int n)
{
if (n == 1)
return 1;
else
return n * factorial(n-1);
}
这不会产生任何额外的符号,因为factorial
是在编译时计算的。除了阶乘
本身之外,没有其他符号。您的模板技巧实例化符号以实现相同的效果,但这不是您想要的符号
或者,如果仍要使用模板,但不需要符号,则可以通过enum
使用清单常量
template factorial(int n)
{
static if (n == 1)
enum factorial = 1;
else
enum factorial = n * factorial!(n-1);
}
注意从
const
到enum
的变化enum
值纯粹是编译时的值,因此它们不会在对象文件中生成符号或数据。是否检查了它们是否在可执行文件中。您是否也在调试时编译?我编译时没有调试符号(dmd
没有选项)。我尝试过优化,结果是一样的。如何检查可执行文件=这是一个好问题。我期望static int x=factorial!5
与枚举fac5=58有点相似;静态int x=fac5但它很可能是不同的。静态
创建一个带有地址的变量,而枚举
则复制粘贴到它使用的每个地方。它没有地址,对于数组文本这样的东西,结果是非常不同的,因为只有一个变量是static
,而对于enum
,每次使用enum
时都会实例化一个新的变量。出于好奇,有没有理由使用static int
而不是enum
来表示可能是不可变的东西?@YotaXP:好吧,对于不可变的值,使用immutable
:)无论如何,static
和enum
之间的区别在于enum
不是符号。您不能获取枚举
,枚举
占用零内存的地址,也不能在调试器中检查枚举
的值。使用static immutable
的主要原因是,如果您需要获取地址,或者如果对象太大,您不想将数据复制到整个代码中。例如,enum
数组将在每次使用时创建该数组的副本。在某种意义上,enum
s是内联常量。
template factorial(int n)
{
static if (n == 1)
enum factorial = 1;
else
enum factorial = n * factorial!(n-1);
}