MQL5 Der Compiler unterscheidet nicht zwischen einer Klasse und einem Zeiger auf sie

 

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

Es wird in beiden Fällen kompiliert:

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

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

Im ersten Fall ist die Ausgabe ein Objekt, das nicht gelöscht (neu erstellt) wurde, und ein Speicherleck

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

Ok, manuell freigeben ... und dann bemerkt der Compiler (plötzlich), dass das Array Nicht-Zeiger enthält:"Objektzeiger erwartet"

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

Ok, ich deklariere es als Zeiger-Array.

A* m_A[2];

Es kompiliert! Das war neu für mich. Also, haben MQL Zeiger oder nicht? Denn bei eingebauten Typen wie char, int, etc. gibt es

'*' - pointer cannot be used

Aber dieses Mal wird es zur Laufzeit sein.

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

Was im Prinzip logisch ist).

Zu den Ergebnissen gibt es einige Fragen:

1. Wozu sind diese Subpointer in MQL da, wenn sie nicht ihre Hauptfunktion erfüllen, wie es die Pointer in C/C++ tun?

2. Warum sollten wir mit Löschen spielen, wenn MT auf das Byte genau weiß, wie viel Speicher ausgelaufen ist, und diesen automatisch wieder freigeben kann?

 

Beim Löschen müssen Sie den Zeigertyp überprüfen. Ein Objekt wird mit new erstellt - es muss gelöscht werden (zweites im Beispiel) und das andere ist automatisch (erstes im Beispiel), es wird automatisch gelöscht.

 
Dmitry Fedoseev:

Beim Löschen müssen Sie den Zeigertyp überprüfen. Ein Objekt wird mit new erstellt, es muss gelöscht werden (das zweite im Beispiel), und das andere ist automatisch (das erste im Beispiel), es wird automatisch gelöscht.

D.h. im ersten Fall enthältm_A[0] keine Kopie desStack-Objekts"a", sondern einen Zeiger vomTypPOINTER_AUTOMATIC auf dieses lokale Objekt, der nach Beendigung der Funktion (wenn sie von einer anderen Funktion aus aufgerufen wurde) zumTypPOINTER_INVALID wird?

 
Dann sieht das Problem im Allgemeinen so aus: Der Compiler lässt zu, dass ein Zeiger vom TypPOINTER_AUTOMATIC in einen Zeiger vom TypPOINTER_DYNAMIC gespeichert wirdund umgekehrt.
 
SemenTalonov:

D.h. im ersten Fallistm_A[0] keine Kopie desStack-Objekts"a", sondern ein Zeiger vomTypPOINTER_AUTOMATIC auf dieses lokale Objekt, der nach Beendigung der Funktion (wenn sie von einer anderen Funktion aus aufgerufen wurde) zumTypPOINTER_INVALID wird?

Alles kann zu einem INVALID werden, wenn es nicht richtig verwendet wird. Der Punkt ist nicht, dassPOINTER_INVALID, sondern dass ein automatisch erstelltes Objekt auch automatisch gelöscht wird.

In keinem Fall kann hier eine Kopie eines Objekts erstellt werden. Ein Zeiger ist einfach ein Zeiger - eine Variable mit einer Nummer, die angibt, wo sich das Objekt befindet, in diesem Fall das Objekt "a". Sie können sich also auf das Objekt "a" mit "a" oder "m_A[0]" beziehen, es ist ein Objekt, nicht zwei verschiedene.

Das Prinzip ist einfach: Sie haben das Objekt erstellt, löschen Sie es selbst. Wenn Sie sie nicht geschaffen haben, lassen Sie sie in Ruhe. So einfach ist das.

 
SemenTalonov:
Im Allgemeinen sieht das Problem so aus: Der Compiler erlaubt es Ihnen, einen Zeiger vom TypPOINTER_DYNAMIC in einen Zeiger vom TypPOINTER_AUTOMATIC zu speichernund umgekehrt.

Umgekehrt. Ein Zeiger vom TypPOINTER_DYNAMIC kann einem Zeiger vom TypPOINTER_AUTOMATICzugewiesen werden.Aber das ist richtig und gut - es eröffnet eine Menge Möglichkeiten.

 

Ich verstehe nicht, was los ist?

Wir nehmen ein Array von Objekten und setzen dessen erstes Element mit dem auf dem Stack erstellten Objekt gleich. Gleichzeitig, ohne den Kopieroperator ! Dies ist bereits ein Fehler.

Da es sich um ein sehr einfaches Objekt handelt, wird der Kopierkonstruktor dort standardmäßig erzeugt. Und das Array enthält eine Kopie des erstellten Objekts.

Kein Problem mit den Fragen.

1. Zeiger erfüllen ihre Aufgabe, und ich persönlich vermisse nur Zeiger auf ein Array.

MQL sollte nicht löschen, was es nicht markiert hat. Dmitriy hatte Recht, als er sagte: "Erstelle ein Objekt, lösche es". Ich mag die "Müllsammler"-Praxis in C# nicht, bei der Objekte nicht gelöscht werden, wenn ich es will, sondern wenn der Assembler es will.

 
Georgiy Merts:

Ich verstehe nicht, was los ist?

Wir nehmen ein Array von Objekten und setzen dessen erstes Element mit dem auf dem Stack erstellten Objekt gleich. Gleichzeitig, ohne den Kopieroperator ! Dies ist bereits ein Fehler.

Da es sich um ein sehr einfaches Objekt handelt, wird der Kopierkonstruktor dort standardmäßig erzeugt. Und das Array enthält eine Kopie des erstellten Objekts.

Das ist es, was ich von einer Kopie erwartet habe... Der Standard-Kopierkonstruktor ist kein Fehler.

Dmitry gibt jedoch an, dass ein neues Objekt im Speicher zugewiesen wird und ein Zeiger vom TypPOINTER_AUTOMATIC zurückgegeben wirdund es keine Kopie gibt.

Jeder versteht MQL-Macken auf seine eigene Weise)

 
SemenTalonov:

Das hatte ich von der Kopie erwartet... Der Standard-Kopierkonstruktor ist kein Fehler.

AberDmitry sagt, dass ein neues Objekt im Speicher zugewiesen wird und ein Zeiger vom TypPOINTER_AUTOMATIC zurückgegeben wird.

Jeder versteht MQL-Macken auf seine eigene Weise)

Was meinen Sie mit "kein Fehler"? Sie verwenden einen Operator, der nicht definiert ist.

Nun, Sie haben hier ein praktisch leeres Objekt, aber was wäre, wenn es andere Unterobjekte in diesem Objekt gäbe, die eine Initialisierung erfordern würden, und dieses Objekt selbst würde eine Ressourcenanforderung erfordern?

Für mich klingt das so, als ob man etwas, das nicht deklariert ist, nicht verwenden kann.

"Quirks" habe ich nicht gesehen, ich denke, Dimitri liegt falsch mit "keine Kopie des Objekts" - und der Grund ist wiederum, dass eine nicht deklarierte Anweisung verwendet wird.

 

Woher kommt die Kopie eines Objekts? Eine Kopie eines Zeigers, ja, aber sie zeigt auf dasselbe Objekt.

 
Georgiy Merts:

Was meinen Sie mit "kein Fehler"? Sie verwenden einen Operator, der nicht definiert ist.

Ich will damit sagen, dass ein explizit deklarierter Kopierkonstruktor in diesem Test nichts ändern würde.

Wie kann man das Offensichtliche nicht sehen...

Ein Zeiger geht auf ein Element eines Objekt-Arrays und ein Objekt geht auf ein Element eines Arrays von Zeigern... ist das wirklich in Ordnung?

Im ersten Fall wird das Array zu einem Zeiger auf ein Objekt, im zweiten Fall sollte der Kopierkonstruktor funktionieren, wie können diese Operationen gleichwertig sein?