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

 
SemenTalonov:

Bingo!

SemenTalonov2019.01.10 07:36POINTER_AUTOMATIC type pointerand vice versa.

Not quite a bingo. For simple objects assignment with operator = works. It is not a bug for sure.

 
SemenTalonov:

...

SemenTalonov2019.01.10 07:36POINTER_AUTOMATIC type to a pointer ofPOINTER_DYNAMIC typeand vice versa.

No. When it's not assigning a pointer to automatic, it's copying an object - the values of its fields, but only with simple objects.

 

Forum on trading, automated trading systems and strategy testing

The MQL5 Compiler does not distinguish between a class and a pointer

SemenTalonov, 2019.01.10 04:18

class A
{
public:
    int iValue;
};
//......................
A m_A[2];

void OnStart()
{
A a;

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


Since when are they defined (question to developers)

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

and how do they work? The following compiled code looks delusional

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


And here the situation is not clear

A* m_A[2];

void OnStart()
{
A a;

    m_A[0] =a;  // Почему это работает?
    m_A[0] =&a; // Когда должно работать только это?
}
 
Dmitry Fedoseev:

Not exactly a bingo. For simple objects, assignment with operator = works. Not a bug for sure.

That's right, that's the most important point.

Personally, I believe that you cannot use an assignment operator for objects if this operator is not explicitly defined, even if the objects are simple. We can still somehow agree on the assignment of simple structures. But classes in which constructor is necessarily called (at least implicitly) - can be assigned only by explicitly defined operators.

In my opinion, this was done to make life easier for newbies.

 
Georgiy Merts:

That's right, this is the most important point.

Personally, I believe that you can't use an assignment operator for objects if that operator is not explicitly defined, even if the objects are simple. We can somehow agree on the assignment of simple structures. But classes where constructor is necessarily called (at least, implicitly) - can only be assigned with explicitly defined operators.

In my opinion, this was done to make life easier for beginners.

And complex ones are convenient - without it you can't return MqlTradeRequest, for example. And in structures, a constructor is also necessarily called.

 

There is a theory that MQL is a very stripped-down C#. So it's understandable how MQL compiler behaves in this case. After all, the classes in C# are always placed in the heap, hence:

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

void OnStart()
{
    // Разместили A в куче, указатель на A передали в m_A[1]
    m_A[1] = new A();
    // Разместили A на стеке...
    A a;
    // А вот фиг вам! ля-ля-ля;) Там вам не тут. 'a' - класс и размещается в куче. Указатель на него передается внутреннему сборщику мусора
    // А раз так, то теперь он AUTOMATIC и к нему нельзя применить delete, т.к. внутренний сборщик мусора его удалит сам 
    
    // скопировали указатель a в массив
    m_A[0] = a;
}
//+------------------------------------------------------------------+

Now let's deal with the m_A array. Since m_A is an array of classes and classes are always placed in the heap, there's no need to specify whether array m_A is an array of pointers or an array of objects themselves, because only the first variant always works for classes. Since m_A is always an array of pointers, MQL does not have to specify whether it stores reference types or significant types. Hence, A* m_A[2] == A m_A[2]. Amen.

 
Vasiliy Sokolov:

There is a theory that MQL is a very stripped-down C#. So it's understandable how MQL compiler behaves in this case. After all, the classes in C# are always placed in the heap, hence:

Now let's deal with the m_A array. Since m_A is an array of classes and classes are always placed in the heap, there's no need to specify whether array m_A is an array of pointers or an array of objects themselves, because only the first variant always works for classes. Since m_A is always an array of pointers, MQL does not have to specify whether it stores reference types or significant types. Hence, A* m_A[2] == A m_A[2]. Amen.

Incorrect conclusion. m_A is an array of objects, not pointers. And these objects are completely destroyed. It is not new A that is destroyed.

class A
{
public:
    int iValue;
    
  ~A()
  {
    Print(__FUNCSIG__);
  }
};
//......................
A m_A[2];

void OnStart()
{
A a;
A* b = new A;

    m_A[0] =a;  // копирование объекта, а не указателя
    m_A[1] = b; // копирование объекта, а не указателя
    
  // по выходу уничтожится три объекта
  delete b; // а так - четыре.
}
 
fxsaber:

Incorrect output. m_A is an array of objects, not pointers. And these objects are completely destroyed. It is not new A that is destroyed.

That's a good example. Well, let's move on to thinking about it then.

 

Pfft)) I'm shocked by this.

A m_A[2];

void OnStart()
{
A a;
A* b = new A();

    printf("SizeOf 'a' object: %i SizeOf pointer 'b' to object: %i", sizeof(a), sizeof(b));
    
    a =b;
    b =a;
    
    m_A[0] = a;
    m_A[1] = b;
}
SizeOf 'a' object: 20 SizeOf pointer to 'b' object: 8
 
SemenTalonov:

Phew)) I'm actually shocked by this.

What's wrong with it? In one case an object, in the other case a pointer.