MQL5 The compiler does not distinguish between a class and a pointer to it - page 13

 
Ilya Malev:

It's just not the same in MCL as it is in C++. Here a pointer is not a separate data type at all, so both are objects, and a variable contains its handle.

right?

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

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

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

But I can't say for sure what status the pointer gets after creation:POINTER_INVALID or POINTER_DYNAMIC. In theory, it should be POINTER_INVALID until it gets the address from new.

 
Ilya Malev:

That is, declare

And you'll have exactly the same "auto-object", but you'll have to delete it yourself.

That's not auto...

 
SemenTalonov:

I can't say which status the pointer gets after creation,POINTER_INVALID or POINTER_DYNAMIC. In idea, it should be POINTER_INVALID until new gets the address.

That's correct, the status will be POINTER_INVALID. But variables a and pA are of the same type. Only a is a constant, the constructor is called upon creation and the destructor upon leaving the block, while pA is randomly accessed and the constructor and destructor are called arbitrarily.

A variable declared without * cannot get POINTER_INVALID status without special tricks, this is also true, but not because variables are of different types, but because the compiler well controls constructor and destructor calls, and forbids it to assign another value.

And since variables are essentially the same type, there is no logic for accessing class methods through them differently

 
Ilya Malev:

This is correct, the status will be POINTER_INVALID. But variables a and pA are of the same type. Only a is constant and constructor is called at creation, and destructor at exit from block, and pA is with random access, and with random constructor and destructor calls.

So all the trouble just comes from the fact that you need to distinguish them. I.e. a pointer requires a more responsible attitude (theDYNAMIC one).

 
SemenTalonov:

The only reason for the problem is that they must be distinguished. I.e. a pointer requires a more responsible attitude (theDYNAMIC one).

In my opinion, the point of OOP is only that object references can be passed and stored, and different classes with different behavior can be written in them. Starting to store a reference to an "auto-object" without even touching the polymorphism, you already lose all their distinction (since there are no user variables of type A&)

 
Ilya Malev:

A variable declared without * cannot be given POINTER_INVALID status without special tricks, this is also true, but not because variables are of different types, but because the compiler well controls constructor and destructor calls, and forbids assigning a different value to it.

Exactly. The auto-object pointer will not change its status, while thePOINTER_DYNAMIC pointer might become non-valid at any moment of program execution. The reasons are not so important as the possibility of such an event itself.

 
SemenTalonov:

Exactly. The auto-object pointer will not change its status, while thePOINTER_DYNAMIC pointer might become invalid while the program is running. The reasons are not so important as the possibility of such an event itself.

There is an excellent and safe cure for this:

class A{~A(){}};

void OnStart()
 {
  A*a=new A;
  delete a; // oops =))
 };
Well, I think that programmers should watch over the lifetime of objects and ways of accessing variables and if the architecture is thoroughly thought out from the very beginning errors will be minimized a year or two after writing the code...
 
In fact, the lifetime of the object must match the lifetime of "live" pointers to it. Of course, POINTER_DYNAMIC dynamic object is also a half-way solution, which creates troubles for ill-considered coding. But POINTER_AUTOMATIC also doesn't give me that scalability which I need to handle objects properly. We need it to be like this - if no pointers to object were created when exiting from block, except autovariable where it was created, then delete object. If references were received outside current block - don't delete object while these references still live. Then there will be scalability and the coder won't have to watch deletion by itself all the time... (for example, if you now write A* a = new A; and then a = new A again, the first object will be forever lost and it is guaranteed that there will be memory leak errors in the logs when exiting the program. And where does the famous code optimizer look at that?)
 
Ilya Malev:
Essentially, the lifetime of an object must correspond to the lifetime of "live" pointers to it. Of course, the dynamic object of the mcl POINTER_DYNAMIC type is also a half-optional solution which causes troubles when coding is not very efficient. But POINTER_AUTOMATIC also doesn't give me that scalability which I need to handle objects properly. We need it to be like this - if no pointers to object were created when exiting from block, except autovariable where it was created, then delete object. If references were received outside current block - don't delete object while these references still live. Then there will be scalability and the coder won't have to watch deletion by itself all the time... (for example, if you now write A* a = new A; and then a = new A again, the first object will be forever lost and it is guaranteed that there will be memory leak errors in the logs when exiting the program. And where does the famous code optimizer look at that?)

That was quite a surprise, too. After all, it knows exactly every byte that has escaped, but does not want to release it. So it doesn't watch dino-pointers at all at the moment? It simply counts the difference between memory requested and freed at the end.

And lifetime and empty/lost pointers are just one of the problems. Before we discussed the problems related to implicit conversion of pointers to objects, that's where it's a crash) When by mistake (e.g. the compiler must not have allowed to compile such code), instead of expected pointer you may get a copy of an object by pointer, which in turn may point to nowhere.) Well, you have already written about comparison operations yourself. Everything there is also very implicit.

 
SemenTalonov:

1. That was quite a surprise, too. After all, it knows exactly every byte that has escaped and doesn't want to free it. So it doesn't watch dino-pointers at all at the moment? It just counts the difference between memory requested and memory released at the end.

And lifetime and empty/lost pointers are just one of the problems.

1. Not really, writing a simple GC to dynamic objects would be a piece of cake for developers, but they left these messages on purpose, so that coders could see that they have a glitch in their program. Because their dynamic objects are such a semi-C# (I'm not an expert on it, but from what I've heard) - as if objects behave the same way (no pointers, but everything is objects), and no elaborate subsystem for them has been developed.

2. Well, yes, of course, if object variables were of the same type (that is: deleted not automatically or independently, but by built-in rubbish collector when there are no references to them), then all references to them would be exactly the same.