MQL5 Компилятор не различает класс и указатель на него

 

MT5 build 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

Ок, освобождаем вручную.. и тут компилятор (внезапно) замечает что массив содержит не указатели: "object pointer expected"

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. Зачем в MQL эти недоуказатели если они не выполняют своей главной функции как указатели в том же C/C++?

2. Зачем эти заигрывания с delete если МТ с точностью до байта знает сколько памяти утекло и может освободить её автоматом?

 

При delete надо проверять тип указателя. Один объект создан через new - его надо delete (второй в примере), а другой - автоматический (первый в примере), он автоматически будет удален.

 
Dmitry Fedoseev:

При delete надо проверять тип указателя. Один объект создан через new - его надо delete (второй в примере), а другой - автоматический (первый в примере), он автоматически будет удален.

Т.е. в первом случае в m_A[0] будет не копия стекового объекта 'a', а указатель некоего POINTER_AUTOMATIC типа на тот локальный объект, который после выхода из функции (еслиб это был вызов из другой функции) станет POINTER_INVALID типа?

 
Тогда в общем случае, проблема звучит как: компилятор позволяет, в указатель типа POINTER_AUTOMATIC сохранить указатель типа POINTER_DYNAMIC, и наоборот.
 
SemenTalonov:

Т.е. в первом случае в m_A[0] будет не копия стекового объекта 'a', а указатель некоего POINTER_AUTOMATIC типа на тот локальный объект, который после выхода из функции (еслиб это был вызов из другой функции) станет POINTER_INVALID типа?

INVALID'ом может стать все, что угодно, если им неправильно пользоваться. Дело не в том, что POINTER_INVALID, а в том, что объект созданный автоматически, удален будет тоже автоматически. 

Копии объекта здесь вообще ни в каком случае получится не может. Указатель это просто указатель - переменная с числом указывающим, где находится объект, в данном случае - объект "a". То есть к объекту "a" можно обращаться через "a", а можно через  "m_A[0]", это один объект, а не два разных. 

Принцип простой - сам создал объект - сам удали. Не создавал - не лезь. Проще некуда.

 
SemenTalonov:
Тогда в общем случае, проблема звучит как: компилятор позволяет, в указатель типа POINTER_AUTOMATIC сохранить указатель типа POINTER_DYNAMIC, и наоборот.

Наоборот. Указателю типа POINTER_DYNAMIC можно присвоить указатель типа POINTER_AUTOMATIC. Но это и правильно и хорошо - открывает много возможностей.

 

Что-то я не понял, что не так ?

Берем массив объектов, и первый его элемент приравниваем созданному на стеке объекту. При этом - не объявив оператора копирования ! Это уже ошибка.

Ну, учитывая, что объект очень простой - там генерируется конструктор копирования по умолчанию. И в массиве оказывается копия созданного объекта.

С вопросами - никаких проблем.

1. Указатели - вполне себе выполняют свою роль. Лично мне не хватает только указателей на массив.

2. MQL и не должен удалять то, что он не выделил. Верно выше сказал Дмитрий - создал объект - удали. Мне крайне не нравится практика "уборщика мусора" в том же C#, когда объекты удаляются не тогда, когда это предусмотрено мной, а тогда, когда захочется сборщику.  

 
Georgiy Merts:

Что-то я не понял, что не так ?

Берем массив объектов, и первый его элемент приравниваем созданному на стеке объекту. При этом - не объявив оператора копирования ! Это уже ошибка.

Ну, учитывая, что объект очень простой - там генерируется конструктор копирования по умолчанию. И в массиве оказывается копия созданного объекта.

Вот и я ожидал копии.. Конструктор копирования по умолчанию это не ошибка.

Но Dmitry утверждает что будет выделен новый объект в памяти и вернется указатель типа POINTER_AUTOMATIC а копии не будет.

Каждый по своему понимает причуды MQL)

 
SemenTalonov:

Вот и я ожидал копии.. Конструктор копирования по умолчанию это не ошибка.

Но Dmitry утверждает что будет выделен новый объект в памяти и вернется указатель типа POINTER_AUTOMATIC а копии не будет.

Каждый по своему понимает причуды MQL)

То есть как это "не ошибка" ??? Ты используешь оператор, который не определен.

Хорошо, что там у тебя практически пустой объект, а если бы в этом объекте были бы другие подобъекты, которые бы требовали инициализации, и сам бы этот объект требовал бы запроса ресурсов ?

По мне - ты не можешь использовать то, что не объявлено.

"Причуд" не увидел, Дмитрий, по-моему, не прав насчет "копии объекта не будет" - и причина, опять же, в том, что используется необъявленный оператор.

 

Откуда возьмется копия объекта? Копия указателя  - да, но указывающего на тот же самый объект.

 
Georgiy Merts:

То есть как это "не ошибка" ??? Ты используешь оператор, который не определен.

Я к тому это написал, что объявленный явно конструктор копирования ничего бы в этом тесте не изменил.

Как вы очевидного не замечаете..

в элемент массива объектов ложится указатель и в элемент массива указателей ложится объект.. это действительно нормально?

в первом случае в массив идет указатель на объект во втором случае должен сработать конструктор копирования, как эти операции могут быть равнозначны??