MQL5의 OOP에 대한 질문 - 페이지 70

 
Maxim Kuznetsov :

이것을 "루프 언롤링"이라고 하며 OO 없이 템플릿은 컴파일러에 의해 수행됩니다(적어도 그래야 합니다).

중간 코드(어셈블러에서)를 살펴보면 루프 대신 한 행에 N 연산만 있을 것입니다.

함수가 재귀적으로 호출 되면 어떻게 되는지 알려주실 수 있나요?

 
Dmitry Fedoseev :

함수가 재귀적으로 호출 되면 어떻게 되는지 알려주실 수 있나요?

목적 함수의 재귀 호출이 없습니다 :-)

N:=const 링크가 제공하는 예제에서 재귀는 템플릿에서 코드를 생성할 때만 수행되며 이는 꼬리입니다. 참고로 const-cycle을 템플릿 재귀로 축소하고 유행어라고 부르는 까다로운 변태

매크로에 주기가 있는 경우 다음과 같이 작성됩니다.

#for x=0, x<N, x++

print("x=%d",x);

#endfor

매크로 프로세서 이후에는 N개의 인쇄 시퀀스로 펼쳐집니다. (실제로는 템플릿 클래스를 통해서만 발생)

즉, 포커스는 컴파일 시간에 N이 알려진 경우에만 작동합니다.

 
Maxim Kuznetsov :

목적 함수의 재귀 호출이 없습니다 :-)

N:=const 링크가 제공하는 예제에서 재귀는 템플릿에서 코드를 생성할 때만 수행되며 이는 꼬리입니다. 참고로 const-cycle을 템플릿 재귀로 축소하고 유행어라고 부르는 까다로운 변태

매크로에 주기가 있는 경우 다음과 같이 작성됩니다.

#for x=0, x<N, x++

print("x=%d",x);

#endfor

매크로 프로세서 이후에는 N개의 인쇄 시퀀스로 펼쳐집니다. (실제로는 템플릿 클래스를 통해서만 발생)

즉, 포커스는 컴파일 시간에 N이 알려진 경우에만 작동합니다.

믿거나 말거나 나는 템플릿이 어떻게 작동하는지, N이 무엇인지, 그리고 그 결과가 무엇인지 알고 있습니다. 그리고 재귀 함수 호출 에 대한 제 질문은 재귀 함수 호출에 대한 것이지 어떻게 되었는지에 대한 것이 아닙니다.

 
Dmitry Fedoseev :

믿거나 말거나 나는 템플릿이 어떻게 작동하는지, N이 무엇인지, 그리고 그 결과가 무엇인지 알고 있습니다. 그리고 재귀 함수 호출 에 대한 제 질문은 재귀 함수 호출에 대한 것이지 어떻게 되었는지에 대한 것이 아닙니다.

"나쁜" 시험 유형입니까? :-) 어쩐지 위의 예가 논의되고 있다고 생각했습니다 .. 내가 틀렸습니다 :-)

컴파일러가 재귀를 꼬리 재귀로 변환할 수 있는 경우(즉시 명시적이거나 지적된 경우) 물리적 재귀는 없을 것입니다. 루프(역 점프)를 만들고 각 반복은 " "이전 스택 프레임을 짓밟습니다.

 
Maxim Kuznetsov :

이런 유형의 시험은 "약하게?" :-) 어쩐지 위의 예가 논의되고 있다고 생각했습니다 .. 내가 틀렸습니다 :-)

컴파일러가 재귀를 꼬리 재귀로 변환할 수 있는 경우(즉시 명시적이거나 지적된 경우) 물리적 재귀는 없을 것입니다. 루프(역 점프)를 만들고 각 반복은 " "이전 스택 프레임을 짓밟습니다.

그리고 약한가요? 그냥 질문입니다. 방법이 없습니다.

 
fxsaber :

장난치고 싶지도 않습니다. 간단한 구조를 만들었습니다.



단순 구조의 첫 번째 필드에 대한 액세스가 크기에 따라 달라지는 이유는 명확하지 않습니다.

말. 모든 것이 진부합니다 - 곱셈을 위한 비트 수가 더 큽니다)))) 구조 크기의 이진 표현에서 비트 수가 동일한지 확인하십시오))) 프로세서뿐만 아니라 사람, 1111 * 101을 1111 * 10보다 길게 곱하려면)
 
Vladimir Simakov :
말. 모든 것이 진부합니다 - 곱셈을 위한 비트 수가 더 큽니다)))) 구조 크기의 이진 표현에서 비트 수가 동일한지 확인하십시오))) 프로세서뿐만 아니라 인, 곱하기 1111 * 101은 1111 * 10보다 길다)

확인하지 않겠습니다. 다른 작업이 많이 있습니다. 하지만 믿기 어렵습니다.

 

ME에서 mqh로 작업하고 ALT+N을 누릅니다. 파일 위치는 네비게이터 창의 트리 보기에 표시됩니다.

이제 열린 mq5 파일에 포함하고 싶습니다. 트리에서 mq5로 mqh를 마우스로 드래그했는데 해당하는 인클루드 라인이 생성되지 않습니다.

 
fxsaber :

확인하지 않겠습니다. 다른 작업이 많이 있습니다. 하지만 믿기 어렵습니다.

 template < typename T>
size_t Func(T* arr,size_t arrSize)
{
000000013 FFC1DA0  mov         qword ptr [rsp+ 10 h],rdx  
000000013 FFC1DA5  mov         qword ptr [rsp+ 8 ],rcx  
000000013 FFC1DAA  push        rbp  
000000013 FFC1DAB  push        rdi  
000000013 FFC1DAC  sub         rsp, 148 h  
000000013 FFC1DB3  lea         rbp,[rsp+ 20 h]  
000000013 FFC1DB8  mov         rdi,rsp  
000000013 FFC1DBB  mov         ecx, 52 h  
000000013 FFC1DC0  mov         eax, 0 CCCCCCCCh  
000000013 FFC1DC5  rep stos    dword ptr [rdi]  
000000013 FFC1DC7  mov         rcx,qword ptr [rsp+ 168 h]  
000000013 FFC1DCF  lea         rcx,[__116109BC_Test@cpp ( 013 FFD5029h)]  
000000013 FFC1DD6  call        __CheckForDebuggerJustMyCode ( 013 FFC10B9h)  
     // Write
     for (size_t i = 0 ; i <arrSize; ++i)
000000013 FFC1DDB  mov         qword ptr [rbp+ 8 ], 0   
000000013 FFC1DE3  jmp         Func<STRUCT1>+ 50 h ( 013 FFC1DF0h)  
000000013 FFC1DE5  mov         rax,qword ptr [rbp+ 8 ]  
000000013 FFC1DE9  inc         rax  
000000013 FFC1DEC  mov         qword ptr [rbp+ 8 ],rax  
000000013 FFC1DF0  mov         rax,qword ptr [arrSize]  
000000013 FFC1DF7  cmp         qword ptr [rbp+ 8 ],rax  
000000013 FFC1DFB  jae         Func<STRUCT1>+ 71 h ( 013 FFC1E11h)  
        arr[i].i = i;
000000013 FFC1DFD  imul        rax,qword ptr [rbp+ 8 ], 18 h  
000000013 FFC1E02  mov         rcx,qword ptr [arr]  
000000013 FFC1E09  mov         edx,dword ptr [rbp+ 8 ]  
000000013 FFC1E0C  mov         dword ptr [rcx+rax],edx  
000000013 FFC1E0F  jmp         Func<STRUCT1>+ 45 h ( 013 FFC1DE5h)  

    size_t Sum = 0 ;
000000013 FFC1E11  mov         qword ptr [Sum], 0   

     // Read
     for (size_t i = 0 ; i < arrSize; ++i)
000000013 FFC1E19  mov         qword ptr [rbp+ 48 h], 0   
000000013 FFC1E21  jmp         Func<STRUCT1>+ 8 Eh ( 013 FFC1E2Eh)  
000000013 FFC1E23  mov         rax,qword ptr [rbp+ 48 h]  
000000013 FFC1E27  inc         rax  
000000013 FFC1E2A  mov         qword ptr [rbp+ 48 h],rax  
000000013 FFC1E2E  mov         rax,qword ptr [arrSize]  
000000013 FFC1E35  cmp         qword ptr [rbp+ 48 h],rax  
000000013 FFC1E39  jae         Func<STRUCT1>+ 0 BBh ( 013 FFC1E5Bh)  
        Sum += arr[i].i;
000000013 FFC1E3B  imul        rax,qword ptr [rbp+ 48 h], 18 h  
000000013 FFC1E40  mov         rcx,qword ptr [arr]  
000000013 FFC1E47  movsxd      rax,dword ptr [rcx+rax]  
000000013 FFC1E4B  mov         rcx,qword ptr [Sum]  
000000013 FFC1E4F  add         rcx,rax  
000000013 FFC1E52  mov         rax,rcx  
000000013 FFC1E55  mov         qword ptr [Sum],rax  
000000013 FFC1E59  jmp         Func<STRUCT1>+ 83 h ( 013 FFC1E23h)  

     return Sum + arrSize;
000000013 FFC1E5B  mov         rax,qword ptr [arrSize]  
000000013 FFC1E62  mov         rcx,qword ptr [Sum]  
000000013 FFC1E66  add         rcx,rax  
000000013 FFC1E69  mov         rax,rcx  
}
000000013 FFC1E6C  lea         rsp,[rbp+ 128 h]  

이것은 작은 구조를위한 것입니다

 template < typename T>
size_t Func(T* arr,size_t arrSize)
{
000000013 FFC1EB0  mov         qword ptr [rsp+ 10 h],rdx  
000000013 FFC1EB5  mov         qword ptr [rsp+ 8 ],rcx  
000000013 FFC1EBA  push        rbp  
000000013 FFC1EBB  push        rdi  
000000013 FFC1EBC  sub         rsp, 148 h  
000000013 FFC1EC3  lea         rbp,[rsp+ 20 h]  
000000013 FFC1EC8  mov         rdi,rsp  
000000013 FFC1ECB  mov         ecx, 52 h  
000000013 FFC1ED0  mov         eax, 0 CCCCCCCCh  
000000013 FFC1ED5  rep stos    dword ptr [rdi]  
000000013 FFC1ED7  mov         rcx,qword ptr [rsp+ 168 h]  
000000013 FFC1EDF  lea         rcx,[__116109BC_Test@cpp ( 013 FFD5029h)]  
000000013 FFC1EE6  call        __CheckForDebuggerJustMyCode ( 013 FFC10B9h)  
     // Write
     for (size_t i = 0 ; i <arrSize; ++i)
000000013 FFC1EEB  mov         qword ptr [rbp+ 8 ], 0   
000000013 FFC1EF3  jmp         Func<STRUCT3>+ 50 h ( 013 FFC1F00h)  
000000013 FFC1EF5  mov         rax,qword ptr [rbp+ 8 ]  
000000013 FFC1EF9  inc         rax  
000000013 FFC1EFC  mov         qword ptr [rbp+ 8 ],rax  
000000013 FFC1F00  mov         rax,qword ptr [arrSize]  
000000013 FFC1F07  cmp         qword ptr [rbp+ 8 ],rax  
000000013 FFC1F0B  jae         Func<STRUCT3>+ 71 h ( 013 FFC1F21h)  
        arr[i].i = i;
000000013 FFC1F0D  imul        rax,qword ptr [rbp+ 8 ], 58 h  
000000013 FFC1F12  mov         rcx,qword ptr [arr]  
000000013 FFC1F19  mov         edx,dword ptr [rbp+ 8 ]  
000000013 FFC1F1C  mov         dword ptr [rcx+rax],edx  
000000013 FFC1F1F  jmp         Func<STRUCT3>+ 45 h ( 013 FFC1EF5h)  

    size_t Sum = 0 ;
000000013 FFC1F21  mov         qword ptr [Sum], 0   

     // Read
     for (size_t i = 0 ; i < arrSize; ++i)
000000013 FFC1F29  mov         qword ptr [rbp+ 48 h], 0   
000000013 FFC1F31  jmp         Func<STRUCT3>+ 8 Eh ( 013 FFC1F3Eh)  
000000013 FFC1F33  mov         rax,qword ptr [rbp+ 48 h]  
000000013 FFC1F37  inc         rax  
000000013 FFC1F3A  mov         qword ptr [rbp+ 48 h],rax  
000000013 FFC1F3E  mov         rax,qword ptr [arrSize]  
000000013 FFC1F45  cmp         qword ptr [rbp+ 48 h],rax  
000000013 FFC1F49  jae         Func<STRUCT3>+ 0 BBh ( 013 FFC1F6Bh)  
        Sum += arr[i].i;
000000013 FFC1F4B  imul        rax,qword ptr [rbp+ 48 h], 58 h  
000000013 FFC1F50  mov         rcx,qword ptr [arr]  
000000013 FFC1F57  movsxd      rax,dword ptr [rcx+rax]  
000000013 FFC1F5B  mov         rcx,qword ptr [Sum]  
000000013 FFC1F5F  add         rcx,rax  
000000013 FFC1F62  mov         rax,rcx  
000000013 FFC1F65  mov         qword ptr [Sum],rax  
000000013 FFC1F69  jmp         Func<STRUCT3>+ 83 h ( 013 FFC1F33h)  

     return Sum + arrSize;
000000013 FFC1F6B  mov         rax,qword ptr [arrSize]  
000000013 FFC1F72  mov         rcx,qword ptr [Sum]  
000000013 FFC1F76  add         rcx,rax  
000000013 FFC1F79  mov         rax,rcx  
}
000000013 FFC1F7C  lea         rsp,[rbp+ 128 h]  

이것은 큰 것을위한 것입니다.

VS2019, Debug x64, 릴리스 버전에서 인라인했지만 속도는 동일합니다.

유일한 차이점은 imul 명령어, 세 번째 피연산자가 두 위치에 있다는 것입니다. 명령어는 배열의 오프셋 계산일 뿐이고 세 번째 피연산자는 구조의 크기( 바이트)입니다.

따라서 신비주의가 없습니다. 물리 법칙이 작용합니다.

 
Vladimir Simakov :

따라서 신비주의가 없습니다. 물리 법칙이 작용합니다.

다음과 같이 클래스를 작성하는 경우:

 //+------------------------------------------------------------------+
struct STRUCT
{
   int i;
   double d;
   uchar uc[ 16 ];
};
//+------------------------------------------------------------------+
class A
{
private :
   int i;
   double d;
   uchar uc[ 16 ];
public :
   A( const STRUCT &ini) { i = ini.i; d = ini.d; ArrayCopy (uc,ini.uc); }
};
//+------------------------------------------------------------------+
class B
{
private :
   STRUCT data;
public :
   B( const STRUCT &ini) { data = ini; }
};
//+------------------------------------------------------------------+

연구 결과에 따르면, 계산에 구조 필드를 자주 사용하면 클래스 B 가 느려질까요?