MQL5 컴파일러는 클래스와 이에 대한 포인터를 구분하지 않습니다. - 페이지 5

 
= 기호는 한 객체의 메모리 공간을 다른 객체의 메모리 공간으로 복사합니다. 모든 개체는 원래 있던 위치에 남아 있습니다.
 
Vladimir Simakov :
어쨌든 그에게 전화하지 마십시오. 순수한 메모리 누수.

전화할 수 있는지 확인하십시오.

 

그건 그렇고, 여러분, 개발자 여러분, 여기에서 수정하는 것이 더 좋습니다. 결국 new는 실제로 포인터를 반환하므로 다른 쪽 끝에 =도 포인터인지 확인하고 암시적 캐스트(A) new A()를 제거합니다.

 
Vladimir Simakov :

그건 그렇고, 여러분, 개발자 여러분, 여기에서 수정하는 것이 더 좋습니다. 결국 new는 실제로 포인터를 반환하므로 다른 쪽 끝에 =도 포인터인지 확인하고 암시적 캐스트(A) new A()를 제거합니다.

이 교환원에게 전화가 옵니다

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

MQL5 컴파일러는 클래스와 이에 대한 포인터를 구분하지 않습니다.

fxsaber , 2019.01.10 06:36

언제부터 정의되었습니까(개발자에 대한 질문).

 void A:: operator =( const A& );
void A:: operator =( const A* );

어떻게 작동합니까? 다음 컴파일된 코드는 미친 것처럼 보입니다.

    A* b = NULL ;    
    m_A[ 1 ] = b;    


대충 이렇게 생겼습니다

 class A
{
public :
     int iValue;
    
     void operator =( const A* Ptr )
    {
       Print ( __FUNCSIG__ );
      
       this .iValue = Ptr.iValue;
    }
};
//......................
A m_A[ 2 ];

void OnStart ()
{
A a;

    m_A[ 0 ] =a; 
    m_A[ 1 ] = new A();
}
 
fxsaber :

이 교환원에게 전화가 옵니다


대충 이렇게 생겼습니다

네 이해했습니다. 좋은 그런 갈퀴가 나타났습니다. 그건 그렇고, C ++에는 = 연산자의 과부하가 없습니다. VS는 맹세합니다.
 

그런데 이상한 주제. 소란을 피우기 전에 MQL에서 포인터가 평생 동안 암시적으로 객체에 캐스팅(역참조)되어 왔다는 사실을 아는 것이 좋을 것입니다. 이것은 편리하고 모든 사람이 익숙합니다. 읽기 어려운 항목 a()->b()->c()->d() 대신 일반적인 OOP 형식으로 작성할 수 있습니다 . a().b().c().d( ) , 함수에 전달하는 과정에서 불필요한 변환을 덜 수행합니다. 그리고 지금 누군가의 불만 때문에 모든 것을 바꾸려고 합니까?

 
Alexey Navoykov :

그런데 이상한 주제. 소란을 피우기 전에 MQL에서 포인터가 평생 동안 암시적으로 객체에 캐스팅(역참조)되어 왔다는 사실을 아는 것이 좋을 것입니다. 이것은 편리하고 모든 사람이 익숙합니다. 읽기 어려운 항목 a()->b()->c()->d() 대신 일반적인 OOP 형식으로 작성할 수 있습니다 . a().b().c().d( ) , 함수에 전달하는 과정에서 불필요한 변환을 덜 수행합니다. 그리고 지금 누군가의 불만 때문에 모든 것을 바꾸려고 합니까?

캐스팅 때문이 아니다. 당신은 들어가지 않았다.

 

선언된 MQL 프로토타입에 초점을 맞춘다면 - C++.

C++ 에서 m_A가 객체의 배열인 경우 new 연산자 는 각각 포인터를 반환합니다.

m_A[ 1 ] = new A();

여기에 유형 오류가 있을 것입니다.

이 줄은 컴파일러에서 건너뜁니다.

m_A[ 1 ] = *( new A() );

그러나 메모리 누수가 발생합니다.


MQL이 같은 동작을 했다면 좋았을 것입니다.

 
Alexey Navoykov :

그런데 이상한 주제. 소란을 피우기 전에 MQL에서 포인터가 평생 동안 암시적으로 객체에 캐스팅(역참조)되어 왔다는 사실을 아는 것이 좋을 것입니다. 이것은 편리하고 모든 사람이 익숙합니다. 읽기 어려운 항목 a()->b()->c()->d() 대신 일반적인 OOP 형식으로 작성할 수 있습니다 . a().b().c().d( ) , 함수에 전달하는 과정에서 불필요한 변환을 덜 수행합니다. 그리고 지금 누군가의 불만 때문에 모든 것을 바꾸려고 합니까?

그리고 간단한 예에 대해 자세히 설명합니다.

A a;

// 'a' ожидает объект
 
a = new A(); // а ему дают указатель, ведь можно же

// что в MQL равнозначно?
a = *(A*) new A();

결과적으로 우리는

1. 'a'는 생성된 객체의 복사본을 가져오고 새로 생성된 객체에 대한 포인터는 손실됩니다.

2. new가 객체 생성/메모리 할당에 실패하면 'a'는 어떻게 됩니까?

두 번째 경우(반대의 경우도 마찬가지)

A* a; // глобальный указатель - 'a' ожидает указатель на объект

// далее всё происходит внутри некой функции
A b; // создаем второй в стеке (ну типа в стеке, не суть)

a =b;
// т.е. тут объект "неявно кастится" к указателю?)
a = &b;

1. 함수를 종료한 후 로컬 객체인 'b'를 소멸시켜야 합니다.

그러면 'a'는 무엇을 가리킬까요?

2. 아니면 복사 연산자가 여전히 작동하고 'b'가 'a' 포인터에 복사됩니까? ''가 이전에 정의되지 않은 경우?

 
SemenTalonov :

두 번째 경우(반대의 경우도 마찬가지)

A* a; // глобальный указатель - 'a' ожидает указатель на объект

// далее всё происходит внутри некой функции
A b; // создаем второй в стеке (ну типа в стеке, не суть)

a =b;
// т.е. тут объект "неявно кастится" к указателю?)


여기서 반대로 포인터 암시적으로 개체로 캐스팅(역참조)된 다음 연산자 =가 개체에 적용됩니다. 어제 fxsaber도 이것을 언급했습니다.

그리고 이 경우 그러한 행위를 금지하는 것이 낫다는 데 동의합니다. 논리적으로 MQL 규칙과 모순되지는 않지만(= 연산자를 호출하는 것은 다른 개체 메서드를 호출하는 것과 동일하기 때문에) 이러한 코드에 대한 모호한 인식과 미묘한 오류로 이어집니다. 그리고 이것은 = 연산자뿐만 아니라 적어도 == 및 !=에도 적용됩니다. 그리고 아마도 다른 운영자에게는 그러한 캐스팅을 금지해야 할 필요가 있습니다. C++에서는 +-<>[] 연산자에 적용할 수 있기 때문입니다.

간단히 말해서 평결은 다음과 같습니다. C++에서 포인터에 대해 허용되는 포인터에 연산자를 적용할 때 이 포인터를 개체에 암시적으로 캐스팅하는 것을 금지합니다. 따라서 위의 예에서는 컴파일 오류가 발생 합니다.