MQL5 Il compilatore non distingue tra una classe e un puntatore ad essa

 

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

Compila in entrambi i casi:

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

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

Nel primo caso, l'output è un oggetto che non viene cancellato (creato nuovo) e una perdita di memoria

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

Ok, liberando manualmente ... e poi il compilatore (improvvisamente) si accorge che l'array contiene non-pointer:"object pointer expected"

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

Ok, lo dichiaro come un array di puntatori.

A* m_A[2];

Compila! Questa era una novità per me. Quindi, MQL ha dei puntatori o no? Perché con i tipi incorporati, come char, int, ecc.

'*' - pointer cannot be used

Ma questa volta sarà in fase di esecuzione.

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

Il che è logico in linea di principio).

Ci sono alcune domande sui risultati:

1. A cosa servono questi sottopuntatori in MQL, se non servono alla loro funzione principale, come fanno i puntatori in C/C++?

2. Perché dovremmo giocare con la cancellazione, se MT sa al byte esatto quanta memoria è fuoriuscita e può rilasciarla automaticamente?

 

Quando si cancella, bisogna controllare il tipo di puntatore. Un oggetto è creato con new - deve essere cancellato (secondo nell'esempio) e l'altro è automatico (primo nell'esempio), sarà cancellato automaticamente.

 
Dmitry Fedoseev:

Quando si cancella, bisogna controllare il tipo di puntatore. Un oggetto è creato con new - deve essere cancellato (secondo nell'esempio), e l'altro è automatico (primo nell'esempio), sarà cancellato automaticamente.

Cioè nel primo casom_A[0] non conterràuna copia dell'oggettostack'a' ma un puntatore di qualchetipoPOINTER_AUTOMATICO a quell'oggetto locale che diventerà ditipoPOINTER_INVALID dopo l'uscita dalla funzione (se fosse chiamata da un'altra funzione)?

 
Allora, in generale, il problema suona così: il compilatore permette di salvare un puntatore di tipoPOINTER_AUTOMATIC in un puntatore di tipoPOINTER_DYNAMIC, e viceversa.
 
SemenTalonov:

Cioè nel primo casom_A[0] non sarà una copia dell'oggettostack'a' ma un puntatore di qualchetipoPOINTER_AUTOMATICO a quell'oggetto locale che diventerà ditipoPOINTER_INVALID dopo l'uscita dalla funzione (se fosse chiamata da un'altra funzione)?

Qualsiasi cosa può diventare un INVALIDO, se non è usata correttamente. Il punto non è chePOINTER_INVALID, ma che un oggetto creato automaticamente sarà anche cancellato automaticamente.

In nessun caso una copia di un oggetto può essere creata qui. Un puntatore è solo un puntatore - una variabile con un numero che indica dove si trova l'oggetto, in questo caso l'oggetto "a". Quindi, potete riferirvi all'oggetto "a" con "a", o potete farlo con "m_A[0]", è un solo oggetto, non due diversi.

Il principio è semplice: avete creato l'oggetto, cancellatelo voi stessi. Se non l'hai creato tu, lascialo stare. È così facile.

 
SemenTalonov:
In generale, il problema suona così: il compilatore permette di salvare un puntatore di tipoPOINTER_AUTOMATIC in un puntatore di tipoPOINTER_DYNAMIC e viceversa.

Viceversa. Un puntatore di tipoPOINTER_DYNAMIC può essere assegnato a un puntatore di tipoPOINTER_AUTOMATIC. Ma questo è corretto e buono - apre un sacco di possibilità.

 

Non capisco cosa c'è che non va?

Prendiamo un array di oggetti ed equipariamo il suo primo elemento all'oggetto creato sullo stack. Allo stesso tempo, senza dichiarare l'operatore di copia ! Questo è già un errore.

Bene, tenendo conto che l'oggetto è molto semplice, il costruttore di copia è generato lì per default. E l'array contiene una copia dell'oggetto creato.

Nessun problema con le domande.

1. I puntatori adempiono al loro ruolo, e personalmente mi mancano solo i puntatori a un array.

MQL non dovrebbe cancellare ciò che non ha segnato. Dmitriy aveva ragione quando diceva: "Crea un oggetto, cancellalo". Non mi piace la pratica del "raccoglitore di spazzatura" in C# dove gli oggetti vengono cancellati non quando voglio io ma quando lo vuole l'assemblatore.

 
Georgiy Merts:

Non capisco cosa c'è che non va?

Prendiamo un array di oggetti ed equipariamo il suo primo elemento all'oggetto creato sullo stack. Allo stesso tempo, senza dichiarare l'operatore di copia ! Questo è già un errore.

Bene, tenendo conto che l'oggetto è molto semplice, il costruttore di copia è generato lì per default. E l'array contiene una copia dell'oggetto creato.

È quello che mi aspettavo una copia di... Il costruttore di copie predefinito non è un errore.

MaDmitry afferma che un nuovo oggetto verrà allocato in memoria e verrà restituito un puntatore di tipoPOINTER_AUTOMATIC e non ci sarà alcuna copia.

Ognuno capisce le stranezze di MQL a modo suo)

 
SemenTalonov:

Questo è quello che mi aspettavo dalla copia... Il costruttore di copie predefinito non è un errore.

MaDmitry dice che un nuovo oggetto verrà allocato in memoria e verrà restituito un puntatore di tipoPOINTER_AUTOMATIC.

Ognuno capisce le stranezze di MQL a modo suo)

Cosa vuol dire che "non è un errore"? State usando un operatore che non è definito.

Bene, avete un oggetto praticamente vuoto, ma se ci fossero altri sottooggetti in questo oggetto, che richiederebbero l'inizializzazione, e questo oggetto stesso richiedesse una richiesta di risorse?

Mi sembra che non si possa usare qualcosa che non è dichiarato.

"Stranezze" che non ho visto, penso che Dimitri si sbagli su "nessuna copia dell'oggetto" - e la ragione, di nuovo, è che viene usata una dichiarazione non dichiarata.

 

Da dove viene la copia di un oggetto? Una copia di un puntatore, sì, ma che punta allo stesso oggetto.

 
Georgiy Merts:

Cosa intendi per "nessun errore"? Stai usando un operatore che non è definito.

Il mio punto è che un costruttore di copie dichiarato esplicitamente non cambierebbe nulla in questo test.

Come fai a non vedere l'ovvio...

Un puntatore va a un elemento di un array di oggetti e un oggetto va a un elemento di un array di puntatori... va davvero bene?

nel primo caso l'array va un puntatore a un oggetto nel secondo caso il costruttore di copia dovrebbe funzionare, come possono essere equivalenti queste operazioni?

Motivazione: