MQL5 El compilador no distingue entre una clase y un puntero a ella - página 3

 
SemenTalonov:

¡Bingo!

SemenTalonov2019.01.10 07:36POINTER_AUTOMATICy viceversa.

No es del todo un bingo. Para los objetos simples, la asignación con el operador = funciona. Seguro que no se trata de un error.

 
SemenTalonov:

...

SemenTalonov2019.01.10 07:36POINTER_AUTOMATIC en un puntero de tipoPOINTER_DYNAMIC y viceversa.

No. Cuando no está asignando un puntero a automático, está copiando un objeto - los valores de sus campos, pero sólo con objetos simples.

 

Foro sobre comercio, sistemas de comercio automatizados y pruebas de estrategias

El compilador MQL5 no distingue entre una clase y un puntero

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();
}


Desde cuándo se definen (pregunta a los desarrolladores)

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

¿y cómo funcionan? El siguiente código compilado parece delirante

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


Y aquí la situación no está clara

A* m_A[2];

void OnStart()
{
A a;

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

No es exactamente un bingo. Para los objetos simples, la asignación con el operador = funciona. Seguro que no es un error.

Así es, ese es el punto más importante.

Personalmente, creo que no se puede utilizar un operador de asignación de objetos si éste no está definido explícitamente, aunque los objetos sean simples. Todavía podemos acordar de alguna manera la asignación de estructuras simples. Pero las clases en las que se llama necesariamente al constructor (al menos implícitamente) - sólo pueden ser asignadas por operadores definidos explícitamente.

En mi opinión, esto se hizo para facilitar la vida a los novatos.

 
Georgiy Merts:

Así es, este es el punto más importante.

Personalmente, creo que no se puede utilizar un operador de asignación para objetos si ese operador no está definido explícitamente, aunque los objetos sean simples. Podemos acordar de alguna manera la asignación de estructuras simples. Pero las clases en las que se llama necesariamente al constructor (al menos, implícitamente) - sólo pueden asignarse con operadores definidos explícitamente.

En mi opinión, esto se hizo para facilitar la vida a los principiantes.

Y los complejos son convenientes - sin ellos no se puede devolver MqlTradeRequest, por ejemplo. Y en las estructuras también se llama necesariamente a un constructor.

 

Existe la teoría de que MQL es un C# muy despojado. Así que es comprensible el comportamiento del compilador MQL en este caso. Después de todo, las clases en C# se colocan siempre en el montón, por lo tanto:

//+------------------------------------------------------------------+
//| 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;
}
//+------------------------------------------------------------------+

Ahora vamos a tratar con la matriz m_A. Como m_A es un array de clases y las clases siempre se colocan en el montón, no es necesario especificar si el array m_A es un array de punteros o un array de objetos en sí, porque sólo la primera variante siempre funciona para las clases. Como m_A es siempre un array de punteros, MQL no tiene que especificar si almacena tipos de referencia o tipos significativos. Por lo tanto, A* m_A[2] == A m_A[2]. Amén.

 
Vasiliy Sokolov:

Existe la teoría de que MQL es un C# muy despojado. Así que es comprensible el comportamiento del compilador MQL en este caso. Después de todo, las clases en C# se colocan siempre en el montón, por lo tanto:

Ahora vamos a tratar con la matriz m_A. Como m_A es un array de clases y las clases siempre se colocan en el montón, no es necesario especificar si el array m_A es un array de punteros o un array de objetos en sí, porque sólo la primera variante siempre funciona para las clases. Como m_A es siempre un array de punteros, MQL no tiene que especificar si almacena tipos de referencia o tipos significativos. Por lo tanto, A* m_A[2] == A m_A[2]. Amén.

Conclusión incorrecta. m_A es un array de objetos, no punteros. Y estos objetos están completamente destruidos. No es el nuevo A el que se destruye.

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:

Salida incorrecta. m_A es un array de objetos, no punteros. Y estos objetos están completamente destruidos. No es el nuevo A el que se destruye.

Ese es un buen ejemplo. Bueno, pensemos más.

 

Pfft)) Estoy sorprendido por esto.

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:

Uf)) La verdad es que estoy sorprendido por esto.

¿Qué tiene de malo? En un caso un objeto, en el otro un puntero.

Razón de la queja: