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

 
Ilya Malev:

Просто в МКЛ все видимо не так, как в С++. Тут указатель не является отдельным типом данных ни разу по сути, а поэтому и то и другое является объектом, а в переменной лежит его хендл. 

так?

// тот же класс А что был выше

A a; // будет создан автообъект с реальным выделением памяти и инициализацией. 'a' является указателем со статусом POINTER_AUTOMATIC

A* pA; // память под объект не выделена, объекта нет. pA является указателем со статусом POINTER_INVALID или POINTER_DYNAMIC?

Вот какой статус получит указатель после создания, POINTER_INVALID или POINTER_DYNAMIC, утверждать не буду. По идее, пока не получен адрес от new должен быть POINTER_INVALID.

 
Ilya Malev:

То есть объявите

И будет Вам точно такой же "автообъект", только удалять его Вы будете сами

Это уже не авто..

 
SemenTalonov:

Вот какой статус получит указатель после создания, POINTER_INVALID или POINTER_DYNAMIC, утверждать не буду. По идее, пока не получен адрес от new должен быть POINTER_INVALID.

Все правильно, будет статус POINTER_INVALID. Но переменные а и рА одного и того же типа. Только а константная и конструктор вызывается при создании, а деструктор при выходе из блока, а рА с произвольным доступом, и с произвольным вызовом конструктора и деструктора.

У переменной, объявленной без *, без особых ухищрений нельзя получить статус POINTER_INVALID, это тоже правда, но не потому, что переменные разного типа, а потому что компилятор хорошо контролирует вызовы конструктора и деструктора, и запрещает ей присваивать другое значение.

А поскольку переменные одного типа по сути, нет никакой логики, чтобы доступ к методам класса через них происходил по-разному

 
Ilya Malev:

Все правильно, будет статус POINTER_INVALID. Но переменные а и рА одного и того же типа. Только а константная и конструктор вызывается при создании, а деструктор при выходе из блока, а рА с произвольным доступом, и с произвольным вызовом конструктора и деструктора.

Так весь сыр бор то только от того что их нужно различать. Т.е. указатель требует более ответственного отношения (тот что DYNAMIC).

 
SemenTalonov:

Так весь сыр бор то только от того что их нужно различать. Т.е. указатель требует более ответственного отношения (тот что DYNAMIC).

На мой взгляд смысл ООП только в том, что ссылки на объекты можно передавать и хранить, и в них могут быть записаны разные классы с разным поведением. Начиная хранить ссылку на "автообъект", даже не касаясь полиморфизма, Вы уже теряете все их различие (поскольку пользовательских переменных типа А& не существует)

 
Ilya Malev:

У переменной, объявленной без *, без особых ухищрений нельзя получить статус POINTER_INVALID, это тоже правда, но не потому, что переменные разного типа, а потому что компилятор хорошо контролирует вызовы конструктора и деструктора, и запрещает ей присваивать другое значение.

Именно. Указатель автообъекта своего статуса не изменит, а указатель POINTER_DYNAMIC в процессе работы программы может запросто стать не валидным. Причины не столь важны сколь сама возможность такого события.

 
SemenTalonov:

Именно. Указатель автообъекта своего статуса не изменит, а указатель POINTER_DYNAMIC в процессе работы программы может запросто стать не валидным. Причины не столь важны сколь сама возможность такого события.

Есть отличное и безотказное лекарство от этого:

class A{~A(){}};

void OnStart()
 {
  A*a=new A;
  delete a; // oops =))
 };
Ладно, в общем я считаю что программист сам должен следить за временем жизни объектов и способом доступа к переменным, а продуманная изначально архитектура сведет ошибки к минимуму хоть через год хоть через два после написания кода...
 
По сути срок жизни объекта должен соответствовать сроку жизни "живых" указателей на него. Динамический объект по типу мкл POINTER_DYNAMIC это конечно тоже половинчатое решение, создающее неприятности при непродуманном кодинге. Но и POINTER_AUTOMATIC не дает того уровня масштабируемости, который нужен для нормальной работы с объектами. Нужно чтобы было так - если при выходе из блока не было создано указателей на объект, кроме автопеременной, в которой он был создан - то удалять объект. Если были получены ссылки вне пределов текущего блока - не удалять объект пока живут эти ссылки. Тогда и масштабируемость появится, и следить за удалением самостоятельным постоянно кодеру не придется... (например - если сейчас написать A* a = new A; а потом a = new А ещё раз, первый объект будет навсегда потерян, и при выходе из программы гарантированно будут ошибки утечки памяти в логах. А куда в это время смотрит хваленный оптимизатор кода?)
 
Ilya Malev:
По сути срок жизни объекта должен соответствовать сроку жизни "живых" указателей на него. Динамический объект по типу мкл POINTER_DYNAMIC это конечно тоже половинчатое решение, создающее неприятности при непродуманном кодинге. Но и POINTER_AUTOMATIC не дает того уровня масштабируемости, который нужен для нормальной работы с объектами. Нужно чтобы было так - если при выходе из блока не было создано указателей на объект, кроме автопеременной, в которой он был создан - то удалять объект. Если были получены ссылки вне пределов текущего блока - не удалять объект пока живут эти ссылки. Тогда и масштабируемость появится, и следить за удалением самостоятельным постоянно кодеру не придется... (например - если сейчас написать A* a = new A; а потом a = new А ещё раз, первый объект будет навсегда потерян, и при выходе из программы гарантированно будут ошибки утечки памяти в логах. А куда в это время смотрит хваленный оптимизатор кода?)

Вот это тоже немало удивило. Ведь точно знает каждый утекший байт а освобождать не хочет. Значит на данный момент за дино указателями он не следит вообще? Просто в конце считает разницу между затребованной памятью и освобожденной.

А время жизни и пустые/потерянные указатели только одна из проблем. Ещё раньше мы обсуждали проблемы связанные с неявным приведением указателей к объектам, вот там треш полный) Когда по ошибке (соотв-но компилятор не должен был дать скомпилировать такой код), вместо ожидаемого указателя можно получить, например, копию объекта по указателю, который в свою очередь, может указывать вникуда). Ну а про операции сравнения Вы уже сами писали. Там всё также очень неявно.

 
SemenTalonov:

1. Вот это тоже немало удивило. Ведь точно знает каждый утекший байт а освобождать не хочет. Значит на данный момент за дино указателями он не следит вообще? Просто в конце считает разницу между затребованной памятью и освобожденной.

2. А время жизни и пустые/потерянные указатели только одна из проблем. 

1. Не совсем, написать простой GC динамическим объектам для разработчиков было бы раз плюнуть, но эти сообщения они специально оставили, чтобы кодеры видели, что у них в программе глюк. Потому что их динамические объекты это такое полу-С# (я не спец по нему, но из того, что слышал) - как бы и объекты ведут себя также (указателей нет, а все есть объекты), и продуманной подсистемы для них не разработано.

2. Ну да, разумеется, если бы объектные переменные были одного типа (то есть: удаляемые не автоматически или самостоятельно, а встроенным сборщиком мусора при отсутствии ссылок на них), то и все обращения к ним происходили бы строго единообразно.

Причина обращения: