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

 

MT5 빌드 1940

 //+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
class A
{
public :
     int iValue;
};
//......................
A m_A[ 2 ];

void OnStart ()
{
A a;

    m_A[ 0 ] =a; 
    m_A[ 1 ] = new A();
}
//+------------------------------------------------------------------+

두 경우 모두 컴파일됩니다.

A m_A[ 2 ]; // и так

A* m_A[ 2 ]; // и так

첫 번째 경우 출력은 제거할 수 없는 개체(new에 의해 생성됨) 및 메모리 누수입니다.

 1 undeleted objects left
1 object of type A left
24 bytes of leaked memory

좋아, 수동으로 해제하십시오. 그러면 컴파일러가 (갑자기) 배열에 비 포인터가 포함되어 있음을 알아차립니다. " 개체 포인터가 필요함"

 delete m_A[ 1 ]; // Если 'm_A' массив объектов -> object pointer expected

좋아, 나는 포인터의 배열로 선언한다

A* m_A[ 2 ];

컴파일 중! 이것은 뉴스였습니다. 그래서 MQL에 포인터가 있습니까? 실제로 char , int 등과 같은 내장 유형을 사용하면

 '*' - pointer cannot be used

하지만 지금 실행할 때

m_A[ 0 ] =a; // получаем: "invalid pointer access"

논리적입니다.)

결과는 다음과 같은 질문을 제기합니다.

1. 동일한 C/C++에서 포인터로 주요 기능을 수행하지 않는 경우 MQL에 이러한 언더 포인터가 있는 이유는 무엇입니까?

2. MT가 가장 가까운 바이트로 누출된 메모리의 양을 알고 자동으로 해제할 수 있는 경우 삭제를 시도하는 이유는 무엇입니까?

 

삭제할 때 포인터의 유형을 확인 해야 합니다. 하나의 객체는 new를 통해 생성됩니다. 삭제해야 하며(예제에서 두 번째), 다른 하나는 자동(예제에서 첫 번째)이므로 자동으로 삭제됩니다.

 
Dmitry Fedoseev :

삭제할 때 포인터의 유형을 확인 해야 합니다. 하나의 객체는 new를 통해 생성됩니다. 삭제해야 하며(예제에서 두 번째), 다른 하나는 자동(예제에서 첫 번째)이므로 자동으로 삭제됩니다.

저것들. 첫 번째 경우에 m_A[ 0 ] 에는 스택 개체 ' a' 의 복사본이 포함되지 않지만 해당 로컬 개체에 대한 일부 POINTER_AUTOMATIC 유형의 포인터가 포함됩니다. 이 포인터는 함수를 종료한 후(다른 함수에서 호출한 경우) POINTER_INVALID 유형 되시겠습니까?

 
그러면 일반적으로 문제가 다음과 같이 들립니다. 컴파일러는 POINTER_AUTOMATIC 유형의 포인터에 POINTER_DYNAMIC 유형의 포인터를 저장할 수 있으며 그 반대의 경우도 마찬가지입니다.
 
SemenTalonov :

저것들. 첫 번째 경우에 m_A[ 0 ] 에는 스택 개체 ' a' 의 복사본이 포함되지 않지만 해당 로컬 개체에 대한 일부 POINTER_AUTOMATIC 유형의 포인터가 포함됩니다. 이 포인터는 함수를 종료한 후(다른 함수에서 호출한 경우) POINTER_INVALID 유형 되시겠습니까?

잘못 사용하면 모든 것이 무효가 될 수 있습니다. 요점은 POINTER_INVALID 가 아니라 자동으로 생성된 객체도 자동으로 삭제된다는 점입니다.

일반적으로 여기에 있는 개체의 복사본은 어떤 경우에도 작동하지 않습니다. 포인터는 포인터일 뿐입니다. 개체의 위치를 나타내는 숫자가 있는 변수(이 경우 개체 "a")입니다. 즉, 객체 "a"는 "a"를 통해 액세스하거나 "m_A[0]"을 통해 액세스할 수 있습니다. 이것은 두 개의 다른 객체가 아니라 하나의 객체입니다.

원리는 간단합니다. 그가 직접 객체를 생성하고 직접 삭제합니다. 만들지 않았습니다-등반하지 마십시오. 어디에도 없습니다.

 
SemenTalonov :
그러면 일반적으로 문제가 다음과 같이 들립니다. 컴파일러는 POINTER_AUTOMATIC 유형의 포인터에 POINTER_DYNAMIC 유형의 포인터를 저장할 수 있으며 그 반대의 경우도 마찬가지입니다.

반대의 경우도 마찬가지입니다. POINTER_DYNAMIC 유형의 포인터에 POINTER_AUTOMATIC 유형의 포인터를 할당할 수 있습니다 . 그러나 이것은 옳고 좋은 것입니다. 많은 가능성이 열립니다.

 

내가 이해하지 못하는 것이 있습니까? 무엇이 잘못 되었습니까?

우리는 객체 배열을 취하고 첫 번째 요소를 스택에서 생성된 객체와 동일시합니다. 동시에 - 복사 연산자를 선언하지 않고! 이것은 이미 실수입니다.

글쎄, 객체가 매우 간단하다는 점을 감안할 때 기본 복사 생성자가 거기에서 생성됩니다. 그리고 배열 은 생성된 객체의 복사본을 포함합니다.

질문 - 문제 없습니다.

1. 포인터 - 역할을 충실히 수행합니다. 개인적으로 배열에 대한 포인터만 부족합니다.

2. MQL은 선택하지 않은 것을 제거해서는 안 됩니다. 사실, Dmitry는 위에서 개체를 생성했다고 말했습니다. 삭제합니다. 나는 객체가 내가 제공했을 때가 아니라 수집기가 원할 때 삭제되는 동일한 C#에서 "가비지 수집기"의 관행을 정말로 좋아하지 않습니다.

 
Georgiy Merts :

내가 이해하지 못하는 것이 있습니까? 무엇이 잘못 되었습니까?

우리는 객체 배열을 취하고 첫 번째 요소를 스택에서 생성된 객체와 동일시합니다. 동시에 - 복사 연산자를 선언하지 않고! 이것은 이미 실수입니다.

글쎄, 객체가 매우 간단하다는 점을 감안할 때 기본 복사 생성자가 거기에서 생성됩니다. 그리고 배열 은 생성된 객체의 복사본을 포함합니다.

그것이 내가 복사에 대해 기대했던 것입니다. 기본 복사 생성자는 버그가 아닙니다.

그러나 Dmitry 는 메모리의 새 개체가 할당되고 POINTER_AUTOMATIC 유형의 포인터가 반환되며 복사본이 없을 것이라고 주장합니다.

모두가 각자의 방식으로 MQL의 단점을 이해합니다.)

 
SemenTalonov :

그것이 내가 복사에 대해 기대했던 것입니다. 기본 복사 생성자는 버그가 아닙니다.

그러나 Dmitry 는 메모리의 새 개체가 할당되고 POINTER_AUTOMATIC 유형의 포인터가 반환되며 복사본이 없을 것이라고 주장합니다.

모두가 자신의 방식으로 MQL의 단점을 이해합니다.)

즉, 이것이 어떻게 "오해가 아니다"??? 정의되지 않은 연산자를 사용하고 있습니다.

거기에 거의 빈 객체가 있는 것은 좋지만 초기화가 필요한 다른 하위 객체가 이 객체에 있고 이 객체 자체에 리소스 요청이 필요하다면 어떻게 될까요?

나에게 당신은 선언되지 않은 것을 사용할 수 없습니다.

나는 "특이점"을 보지 못했습니다. 제 생각에는 Dmitry가 "객체의 사본이 없을 것"에 대해 잘못되었습니다. 그리고 그 이유는 다시 선언되지 않은 연산자가 사용되기 때문입니다.

 

개체의 복사본은 어디에서 올까요? 포인터의 복사본 - 예, 하지만 동일한 개체를 가리킵니다.

 
Georgiy Merts :

즉, 이것이 어떻게 "오해가 아니다" ??? 정의되지 않은 연산자를 사용하고 있습니다.

나는 또한 명시적으로 선언된 복사 생성자가 이 테스트에서 아무 것도 변경하지 않을 것이라고 이것을 썼습니다.

어찌 뻔한 것을 보지 않을 수 있겠는가.

포인터는 객체 배열의 요소에 배치되고 객체는 포인터 배열의 요소에 배치됩니다. 이것이 정말 정상입니까?

첫 번째 경우에는 개체에 대한 포인터가 배열로 이동하고 두 번째 경우에는 복사 생성자가 작동해야 하는데 이러한 작업이 어떻게 동일할 수 있습니까?