MQL5 El compilador no distingue entre una clase y un puntero a ella

 

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

Se compila en ambos casos:

A m_A[2]; // и так

A* m_A[2]; // и так

En el primer caso, la salida es un objeto que no se borra (se crea nuevo) y una fuga de memoria

1 undeleted objects left
1 object of type A left
24 bytes of leaked memory

Vale, liberando manualmente... y entonces el compilador (de repente) se da cuenta de que el array contiene no punteros:"object pointer expected"

delete m_A[1]; // Если 'm_A' массив объектов -> object pointer expected

Ok, lo declaro como un array de punteros.

A* m_A[2];

¡Compila! Esto era nuevo para mí. Entonces, ¿tiene MQL punteros o no? Porque con los tipos incorporados, como char, int, etc., habrá

'*' - pointer cannot be used

Pero esta vez será en tiempo de ejecución.

m_A[0] =a; // получаем: "invalid pointer access"

Lo cual es lógico en principio).

Hay algunas preguntas sobre los resultados:

1. ¿Para qué sirven estos subpuntos en MQL, si no cumplen su función principal, como los punteros en C/C++?

2. ¿Por qué debemos jugar con el borrado, si MT sabe hasta el byte exacto cuánta memoria se ha filtrado y puede liberarla automáticamente?

 

Al borrar, hay que comprobar el tipo de puntero. Uno de los objetos se crea con new - debe ser eliminado (segundo en el ejemplo) y el otro es automático (primero en el ejemplo), se eliminará automáticamente.

 
Dmitry Fedoseev:

Al borrar, hay que comprobar el tipo de puntero. Uno de los objetos se crea con new - debe ser eliminado (segundo en el ejemplo), y el otro es automático (primero en el ejemplo), se eliminará automáticamente.

Es decir, en el primer casom_A[0] no contendráuna copia delobjeto dela pila'a' sino un puntero de algúntipoPOINTER_AUTOMATIC a ese objeto local que se convertirá enun tipoPOINTER_INVALID después de salir de la función (si fuera llamada desde otra función)?

 
Entonces, en general, el problema es el siguiente: el compilador permite guardar un puntero de tipoPOINTER_AUTOMATIC en un puntero de tipoPOINTER_DYNAMIC, y viceversa.
 
SemenTalonov:

Es decir, en el primer casom_A[0] no será una copia delobjeto dela pila'a' sino un puntero de algúntipoPOINTER_AUTOMATIC a ese objeto local que se convertirá enel tipoPOINTER_INVALID después de salir de la función (si fuera llamada desde otra función)?

Cualquier cosa puede convertirse en un INVALIDO, si no se utiliza correctamente. La cuestión no es quePOINTER_INVALID, sino que un objeto creado automáticamente también se borrará automáticamente.

En ningún caso se puede crear aquí una copia de un objeto. Un puntero es sólo un puntero - una variable con un número que indica dónde está el objeto, en este caso el objeto "a". Así, puedes referirte al objeto "a" con "a", o puedes hacerlo con "m_A[0]", es un solo objeto, no dos diferentes.

El principio es sencillo: tú has creado el objeto, elimínalo tú mismo. Si no lo has creado tú, déjalo. Es tan fácil como eso.

 
SemenTalonov:
En general, el problema es el siguiente: el compilador permite guardar un puntero de tipoPOINTER_DYNAMIC en un puntero de tipoPOINTER_AUTOMATICy viceversa.

Y viceversa. Un puntero de tipoPOINTER_DYNAMIC puede ser asignado a un puntero de tipoPOINTER_AUTOMATIC. Pero esto es correcto y bueno - abre muchas posibilidades.

 

No entiendo qué pasa.

Tomamos un array de objetos y equiparamos su primer elemento al objeto creado en la pila. ¡Al mismo tiempo, sin declarar el operador de copia ! Esto ya es un error.

Bueno, teniendo en cuenta que el objeto es muy simple, el constructor de copia se genera allí por defecto. Y el array contiene una copia del objeto creado.

No hay problema con las preguntas.

1. Los punteros cumplen su función, y personalmente sólo echo de menos los punteros a un array.

MQL no debería borrar lo que no ha marcado. Dmitriy tenía razón cuando dijo: "Crea un objeto, bórralo". No me gusta la práctica del "recolector de basura" en C# donde los objetos se borran no cuando yo quiero sino cuando el recolector quiere.

 
Georgiy Merts:

No entiendo qué pasa.

Tomamos un array de objetos y equiparamos su primer elemento al objeto creado en la pila. ¡Al mismo tiempo, sin declarar el operador de copia ! Esto ya es un error.

Bueno, teniendo en cuenta que el objeto es muy simple, el constructor de copia se genera allí por defecto. Y el array contiene una copia del objeto creado.

Eso es lo que esperaba una copia de... El constructor de copia por defecto no es un error.

PeroDmitry afirma que se asignará un nuevo objeto en memoria y se devolverá un puntero de tipoPOINTER_AUTOMATIC y no habrá copia.

Cada uno entiende las peculiaridades de MQL a su manera)

 
SemenTalonov:

Eso es lo que esperaba de la copia... El constructor de copia por defecto no es un error.

PeroDmitry dice que se asignará un nuevo objeto en memoria y se devolverá un puntero de tipoPOINTER_AUTOMATIC.

Cada uno entiende las peculiaridades de MQL a su manera)

¿Qué quiere decir que "no es un error"? Está utilizando un operador que no está definido.

Bien, tienes un objeto prácticamente vacío, pero ¿qué pasa si hay otros subobjetos en este objeto, que requerirían inicialización, y este objeto en sí mismo requeriría una solicitud de recursos?

Me parece que no se puede usar algo que no está declarado.

"Rarezas" no he visto, creo que Dimitri se equivoca con lo de "no hay copia del objeto" - y la razón, de nuevo, es que se utiliza una declaración no declarada.

 

¿De dónde sale una copia de un objeto? Una copia de un puntero, sí, pero apuntando al mismo objeto.

 
Georgiy Merts:

¿Qué quiere decir con "no hay error"? Estás usando un operador que no está definido.

Mi punto es que un constructor de copia declarado explícitamente no cambiaría nada en esta prueba.

Cómo no puedes ver lo obvio...

Un puntero va a un elemento de una matriz de objetos y un objeto va a un elemento de una matriz de punteros... ¿está realmente bien?

en el primer caso el array va un puntero a un objeto en el segundo caso debería funcionar el constructor de la copia, ¿cómo pueden ser equivalentes estas operaciones?

Razón de la queja: