Fragen zu OOP in MQL5 - Seite 11

 
Dmitry Fedoseev:

Und da wir gerade von Vögeln sprechen... Deskriptoren sind auch Wegweiser. Und Sie wissen, dass sich am Wort selbst nichts ändert, egal ob es sich um einen Deskriptor, einen Zeiger oder einen Bezeichner handelt.

die physische Umsetzung dieser Worte ist den Nutzern lange verborgen geblieben

Imho ist es mehr oder weniger so

- Deskriptor - ist an die Methode gebunden, die diese Funktionalität im System implementiert

- ein Handle - alles ist dasselbe wie bei einem Deskriptor, aber das Betriebssystem implementiert es

- ein Zeiger und ein Bezeichner sind für die Arbeit mit physischem Speicher gedacht

 
Dmitry Fedoseev:

Und wenn Sie einen Zeiger an eine Funktion übergeben müssen, um ein Objekt in der Funktion zu erstellen, dann funktioniert das auch so:

class CObj{
   public:
   int f(){
      return(33);
   }
};

CObj * obj;

void OnStart(){
  z(obj);
  delete(obj);
}

void z(CObj & o){
   o = new CObj();
}
Das ist eigentlich alles, was Sie über OOP wissen wollten, aber nicht zu fragen wagten)))

Aha, genial.

Diese 17 Zeilen sind eigentlich alles, was man über Fedoseevs Qualifikation als Programmierer wissen muss.

2019.07.05 15:19:56.309 Ungültiger Zeigerzugriff in 'test13.mq5' (11,5)

 
Vasiliy Sokolov:

Guten Tag. Computerspeicher hat die gleiche Leistung, unabhängig davon, ob er im Stack- oder Heap-Kontext verwendet wird. Die dynamische Speicherverwaltung selbst hängt von der Implementierung des Müllsammlers ab: Sie kann z. B. eine Referenzzählung wie in Python (langsamere Variante) oder eine Analyse der Epochen der Objekterzeugung mit Traversierung des Ausführungsgraphen im Hintergrundprozess (Net CLR) sein. Welche Variante in MQL verwendet wird, ist nicht bekannt, aber wir können davon ausgehen, dass sie äußerst effizient ist, da der Benutzer von MQL5 direkten Zugriff auf den Löschoperator hat, was die Arbeit von GC selbst stark vereinfacht. Daher sind Ihre Bedenken bezüglich des Overheads bei der Verwendung von new unbegründet - Sie können gerne dynamischen Speicher verwenden.

Was den "Stapelüberlauf" betrifft, so kann dieser Fall in modernen Systemen nur dann eintreten, wenn eine komplexe Rekursion verwendet wird oder ein Fehler im rekursiven Algorithmus gemacht wird. Ein modernes Programm arbeitet immer im OC-geschützten Modus im virtuellen Adressraum, mit dynamischem Laden von Speicherseiten, also keine Sorge: der Stack wird nicht überlaufen:)

Vielen Dank für die kluge Erklärung.
Aus irgendeinem Grund dachte ich, dass in mql der Aufruf auf dem Stack schneller ist als auf dem Heap, zumal wir die Implementierung des Müllsammlers nicht kennen.
Deshalb habe ich solche Fragen, was ist besser zu verwenden, um die Erstellung von Objekten zu beschleunigen, automatisch oder dynamisch.
Ja, mir ist klar, dass dies von der jeweiligen Aufgabe abhängt, aber nehmen wir zum Beispiel das Versenden von Handelsaufträgen.
Und unsere Aufgabe ist es, die korrektesten Objekte für eine schnelle Verarbeitung zu erstellen.
Wir haben eine benutzerdefinierte Klasse mit beschriebenen Methoden für Handelsanfragen.
Wir kennen die Anzahl der Klasseninstanzen und ihre Methoden.
Und wie Sie andeuten, "der Stapel wird nicht enden".

Daher lautet meine Frage: Welche Methode ist besser zum Erstellen und Löschen von Objekten? Automatisch oder dynamisch?
Ich hatte eine Idee für die synthetische Verwaltung von automatischen Objekten im Allgemeinen.
Das heißt, Sie deklarieren automatische Objekte im Körper der Benutzerfunktion.
Auf diese Weise wird das Objekt auf dem Stack erstellt (theoretisch ist das schneller als der Heap). Wir müssen uns nicht um das automatische Löschen von Objekten kümmern, da die Objektvariable in der benutzerdefinierten Funktion
und das automatische Objekt wird zusätzlich von der Benutzerfunktion selbst auf Zerstörung geprüft, entsprechend der Regel für dynamische Variablen in Funktionen.
Deshalb möchte ich gerne die Meinungen der Teilnehmer dieser Branche hören, die in dieser Hinsicht denken.

 
TheXpert:

Mm-hmm, genial.

Diese 17 Zeilen sind eigentlich alles, was man über Fedoseevs Qualifikationen als Programmierer wissen muss.

2019.07.05 15:19:56.309 Ungültiger Zeigerzugriff in 'test13.mq5' (11,5)

Erstaunlich. Und ich beide kompilieren ohne Fehler (im Moment) und es funktioniert richtig.

Zeichnen Sie das nächste Mal in Photoshop.

 
Roman:

Vielen Dank für die kluge Erklärung.
Aus irgendeinem Grund dachte ich, dass der Aufruf auf dem Mql-Stack schneller ist als auf dem Heap, zumal wir nicht wissen, wie der Müllsammler implementiert ist.
Deshalb habe ich solche Fragen, was ist besser zu verwenden, um die Erstellung von Objekten zu beschleunigen, automatisch oder dynamisch.
Ja, ich verstehe, dass alles von der jeweiligen Aufgabe abhängt, aber nehmen wir zum Beispiel das Versenden von Handelsanfragen.
Und unsere Aufgabe ist es, die korrektesten Objekte für eine schnelle Verarbeitungsleistung zu erstellen.
Wir haben eine Benutzerklasse mit beschriebenen Methoden für Handelsanfragen.
Wir kennen die Anzahl der Klasseninstanzen und ihre Methoden.
Und wie Sie andeuten, "der Stapel wird nicht enden".

Meine Frage lautet daher: Welche Methode ist besser zum Erstellen und Löschen von Objekten? Automatisch oder dynamisch?
Ich hatte eine Idee für die synthetische Verwaltung von automatischen Objekten im Allgemeinen.
Das heißt, Sie deklarieren automatische Objekte im Körper der Benutzerfunktion.
Auf diese Weise wird das Objekt auf dem Stack erstellt (theoretisch ist das schneller als der Heap). Wir müssen uns nicht um das automatische Löschen von Objekten kümmern, da die Objektvariable in der benutzerdefinierten Funktion
und das automatische Objekt wird zusätzlich von der Benutzerfunktion selbst auf Zerstörung geprüft, entsprechend der Regel für dynamische Variablen in Funktionen.
Deshalb möchte ich gerne die Meinungen der Teilnehmer dieser Branche hören, die in dieser Hinsicht denken.

Sie haben richtig gedacht. Der Zugriff auf mit new erstellte Objekte ist viel langsamer. Und hier gibt es keine Müllabfuhr.

 
Igor Makanu:

die physische Umsetzung dieser Worte ist den Nutzern lange verborgen geblieben

imho so:

- Deskriptor - gebunden an eine Methode, die diese Funktionalität im System implementiert

- ein Handle - alles ist dasselbe wie bei einem Deskriptor, aber das Betriebssystem implementiert es

- ein Zeiger und ein Bezeichner bedeuten, dass es sich um eine Operation im physischen Speicher handelt.

Und es macht für uns keinen Unterschied, wie es funktioniert.

 

Ein Ratschlag zu einem anderen Thema. Wenn Sie eine Unterklasse CMyButton von CButton erstellen, können Sie eine Schaltfläche erstellen und dann ihre Eigenschaften außerhalb der Klasse ändern. Im Folgenden wird dies in OnInit() durchgeführt.

Aber wenn ich zusätzliche Felder innerhalb der Kindklasse erstellen und die eingebauten Eigenschaften der CButton-Klasse in neuen Funktionen verwenden möchte, wie kann dies korrekt implementiert werden?

In der Klasse CButton wird das Klassenmitglied m_button im Abschnitt private deklariert.

#include <Controls\Button.mqh>

class CMyButton : public CButton
{ 
  private: 

  public: 
              CMyButton(void){}; 
             ~CMyButton(void){}; 
             
        bool    isPrevState;        // состояние кнопки на предыд.тике, true - была нажата     
        void    setButton();        // создаем кнопку
        void    setProp();          // задаем в ходе программы свойства
}; 

void CMyButton::setButton(void)
{
  // как в этой функции создать кнопку? Я не могу вызвать метод Create()
}

//+------------------------------------------------------------------------------------------------------------------+
//| 
//+------------------------------------------------------------------------------------------------------------------+

CButton Btn;
CMyButton MyBtn;

int OnInit()
  {
  
   Btn.Create(0, "Btn", 0, 50, 50, 120, 75);
   Btn.Text("Standart");
   MyBtn.Create(0, "MyBtn", 0, 50, 200, 150, 225);
   MyBtn.Text("MyBtn");
   
   return(INIT_SUCCEEDED);
  }
 
Dmitry Fedoseev:

Ja, es löscht und schreibt eine Meldung über Speicherlecks, nur damit die Programmierer, die EAs schreiben, sich nicht langweilen.

Es ist interessant, dass es gestern noch ein Speicherleck gab und heute nicht einmal mehr eines sein kann.

Und da wir gerade von Vögeln sprechen... Deskriptoren sind auch Wegweiser. Das Wort selbst ändert nichts, egal ob es sich um einen Deskriptor, einen Zeiger oder einen Bezeichner handelt.

Das Leck stammt aus dem Adressraum des Prozesses. Wenn Sie in einer while(true)-Schleife ein Leck haben, stürzt Ihr Programm schließlich bei der nächsten Speicherzuweisung aus dem Heap ab, wenn dieser aufgebraucht ist.
 
Dmitry Fedoseev:

Und ich beide kompilieren ohne Fehler (im Moment) und es funktioniert richtig.

Ja, bereits zwei nicht miteinander verbundene Personen haben den Absturz Ihres Codes mit Photoshop bearbeitet)

Ihr Code kann nicht richtig funktionieren, das ist durch den Code selbst offensichtlich ))

 
TheXpert:

Ja, zwei Personen, die nichts mit Ihnen zu tun haben, sind bereits dabei, Ihren Code mit Fotos zu bearbeiten.)

Ihr Code kann nicht richtig funktionieren, das ist aus dem Code selbst ersichtlich ))

Wollte gerade das Gleiche schreiben))))