D函数返回自动引用

Cec*_*ard 2 d reference function return-type

函数的返回类型自动引用是什么意思?我只是不理睬它.我从AliÇehreli的在线书籍中选取了一个例子,并尝试以各种方式对其进行了调整,并观察了GDC生成的汇编程序,我仍然没有更明智.(我是一位非常有经验的asm和C程序员,但是D的新手.)你真的需要使用这个功能吗?

Ada*_*ppe 6

auto返回函数的主要用例位于模板中,函数体根据某些编译时参数进行更改.auto ref只是将其扩展到允许ref返回.看吧:

auto ref foo(string magic)() {
   static if(magic == "use ref") {
     int* x = new int;
     return *x;
   } else {
     return 0;
   }
}

void main() {
        foo!""();
        foo!"use ref"();
}
Run Code Online (Sandbox Code Playgroud)

每个唯一的编译时参数集将生成不同的函数.这些不同的功能有完全不同的代码.

这是一个空字符串的函数:

Disassembly of section .text._D3iii15__T3fooVAyaa0_Z3fooFNaNbNiNfZi:

00000000 <_D3iii15__T3fooVAyaa0_Z3fooFNaNbNiNfZi>:
   0:   31 c0                   xor    eax,eax
   2:   c3                      ret
   3:   90                      nop
   4:   90                      nop
   5:   90                      nop
   6:   90                      nop
   7:   90                      nop
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,这是最微不足道的 - return 0.那里没有花哨的参考.这是一个use ref:

Disassembly of section .text._D3iii29__T3fooVAyaa7_75736520726566Z3fooFNaNbNcNfZi:

00000000 <_D3iii29__T3fooVAyaa7_75736520726566Z3fooFNaNbNcNfZi>:
   0:   55                      push   ebp
   1:   8b ec                   mov    ebp,esp
   3:   b8 00 00 00 00          mov    eax,0x0
   8:   50                      push   eax
   9:   e8 fc ff ff ff          call   a <_D3iii29__T3fooVAyaa7_75736520726566Z3fooFNaNbNcNfZi+0xa>
   e:   83 c4 04                add    esp,0x4
  11:   5d                      pop    ebp
  12:   c3                      ret
  13:   90                      nop
  14:   90                      nop
  15:   90                      nop
  16:   90                      nop
  17:   90                      nop
Run Code Online (Sandbox Code Playgroud)

(被破坏的名称中的字符串为ascii的十六进制字符串(好吧,它实际上是UTF-8,unicode也可以!)字节btw,即75736520726566部分 - 将0x75识别为'u',将0x66识别为'f' D被破坏的名字可能会变得非常漫长,但是一旦你了解它,这个模式很容易阅读.)

该代码调用new,所以正文更复杂,但请注意,eax仍然保持那里的返回值......指针.现在,让我们ref拿出auto ref并重新编译同样的东西.

当然,第一个功能仍然是相同的.第二个改变了:

Disassembly of section .text._D3iii29__T3fooVAyaa7_75736520726566Z3fooFNaNbNfZi:

00000000 <_D3iii29__T3fooVAyaa7_75736520726566Z3fooFNaNbNfZi>:
   0:   55                      push   ebp
   1:   8b ec                   mov    ebp,esp
   3:   b8 00 00 00 00          mov    eax,0x0
   8:   50                      push   eax
   9:   e8 fc ff ff ff          call   a<_D3iii29__T3fooVAyaa7_75736520726566Z3fooFNaNbNfZi+0xa>
   e:   8b 00                   mov    eax,DWORD PTR [eax]
  10:   83 c4 04                add    esp,0x4
  13:   5d                      pop    ebp
  14:   c3                      ret
  15:   90                      nop
  16:   90                      nop
  17:   90                      nop
Run Code Online (Sandbox Code Playgroud)

看到了mov eax,DWORD PTR [eax]吗?它不再返回指针(当然,它是ref引擎盖下的返回),但现在它指向它 - 一个正常的,非ref,值返回.

这就是auto回归和回归之间的区别auto ref.

为了完整起见,让我们改变它ref int,看看会发生什么:

$ dmd iii
iii.d(6): Error: constant 0 is not an lvalue
iii.d(11): Error: template instance iii.foo!"" error instantiating
Run Code Online (Sandbox Code Playgroud)

现在只是return 0因为那不是一个有效的错误ref.

实际使用案例是模板可以基于各种参数做出更复杂的决定,决定在他们的身体中做什么,从而做出返回类型.它可能只返回传递给它的参数的任何类型,它可能会检查平台版本(这是一些丑陋的代码大声笑),无论如何.auto ref允许您自己涵盖各种情况,而无需自己编写单独的函数签名(以及函数体).