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

在D中处理模板递归时,我发现经典阶乘的中间结果仍然在对象文件中。我想它们也在可执行文件中

我可以看到,实际执行的代码只包含值(或指向它的指针),但:

如果中间数据没有被无故保存,难道不应该有一个
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);
}