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允许您自己涵盖各种情况,而无需自己编写单独的函数签名(以及函数体).