2016-08-19 3 views
2

함수에 대한 반환 유형 자동 참조는 무엇을 의미합니까? 나는 그것을 마시지 않는다. 나는 Ali Çehreli의 온라인 서적에서 예제 중 하나를 가져 와서 다양한 방법으로 실험하고 GDC에서 생성 된 어셈블러를 살펴본 결과, 나는 여전히 현명하지 않다. (필자는 매우 숙련 된 asm 및 C 프로그래머이지만 D에 익숙하지 않습니다.) 언제이 기능을 실제로 사용해야합니까?자동 참조를 반환하는 D 함수

답변

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"(); 
} 

각각의 고유 한 컴파일 타임 인수 집합은 다른 기능을 생성합니다. 다른 기능들은 완전히 다른 코드를 가지고 있습니다. - return 0 당신이 볼 수 있듯이

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 

, 그것은 가장 간단하다 :

빈 문자열 기능입니다. 환상적인 심판은 거기에 반환하지 않습니다.) 유니 코드도 작동

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 

합니다 (변환 된 이름이 아니라, 실제로 UTF-8 (아스키의 16 진수 문자열로 문자열을 가지고 75736520726566을 것을, BTW 바이트 :!이 use ref와 하나입니다 부분 - 'u'로 0x75를, 'f'로 0x66을 인식합니다. 맹 글씨로 된 이름은 길어질 수 있지만 패턴은 매우 간단합니다.

해당 코드는 new을 호출하므로 본문은 더 복잡하지만 eax가 반환 값을 여전히 보유하고 있음을 알 수 있습니다. 포인터입니다. 자, 을 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 

mov eax,DWORD PTR [eax]을 참조하십시오. 더 이상 포인터를 반환하지 않습니다 (당연히 ref 반환이 후드에서 수행하는 것입니다). 그러나 이제는 그 포인터가 가리키는 것 - 정상적인 비 - 참조, 값 반환.

auto 답장과 auto ref의 차이점은 다음과 같습니다.

그냥 완성도를 들어, ref int로 변경하고 어떻게되는지 보자 그 유효한 ref하지 않기 때문에

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

은 지금은 에러 단지 return 0입니다.

실제 사용 사례는 템플릿이 모든 종류의 인수에 따라 본문에서 수행 할 작업과 반환 유형에 대해보다 복잡한 결정을 내릴 수 있다는 것입니다. 인수가 전달 된 형식을 반환 할 수도 있고, 플랫폼 버전 (일부 코드가 추한 코드 일 수도 있음)을 확인할 수도 있습니다. auto ref을 사용하면 별도의 기능 서명 (즉, 기능 본문)을 직접 작성하지 않고도 이와 같은 다양한 케이스를 처리 할 수 ​​있습니다.

+0

훌륭한 답변. 고맙습니다. 이것은 더 널리 공표되어야한다. –

+0

자동 참조, 지능형 코드 해결 도구, 그냥 make-it-work 기능. –

+0

[오프 주제] btw 이것은 C++의 최신 방언의 기능을 넘어 있습니까? (나는 C++에 대해 아무것도 몰라, 단지 많은 ASM과 C 만 전문적으로 알고있다.) –

1

auto은 컴파일러에서 함수가 반환 할 유형을 파악하려는 경우에 사용됩니다.예를 들어, 두 기능들은 아래와 같다 :

uint returnAUint(){ 
    uint r=256; 
    return r; 
} 
auto function2(){ 
    uint r=256; 
    return r; 
} 

ref 및 함수 포인터/레퍼런스를 반환한다는 것을 의미한다. 따라서 auto ref은 컴파일러가 알아 내야하는 데이터 유형에 대한 포인터를 반환하는 함수입니다.

관련 문제