Generische Klassenbibliothek - Bugs, Beschreibung, Fragen, Nutzungsmöglichkeiten und Vorschläge - Seite 26

 
Andrey Pogoreltsev:

Sie erstellen Kopien von Objekten in AddValue über new, aber Sie geben sie nicht im Destruktor frei, sondern löschen nur die Liste der Zeiger.

Hilfe besagt, dass beim Aufruf eines Destruktors auch die Destruktoren der von Ihnen verwendeten Klassen aufgerufen werden

https://www.mql5.com/ru/docs/standardlibrary/datastructures/carrayobj#carrayobjfeatures

Ich kann mich an keinen Fall erinnern, in dem das Terminal nach dem Entladen des Skripts nicht eine Warnung über nicht zerstörte Objekte in das Protokoll geschrieben hat - mein Beispiel zeigt keine solche Warnung


Andrey Pogoreltsev:

Zweitens hätten Sie es korrekt mit dem Kopierkonstruktor statt mit dem Zuweisungsoperator machen sollen. Aber das ist alles IMHO)

Ich habe Informationen von Entwicklern gefunden, dass einfache Strukturen oder Klassen in MQL immer ohne Probleme kopiert werden, ich habe es mehrmals überprüft und es scheint wahr zu sein, solange ich die Sprachfunktionen verwende


Das ist es, worum es in der Diskussion geht - MQL ist nicht C++, ich habe aufgehört, nach Analogien zwischen ihnen zu suchen, wenn Entwickler geschrieben haben, dass es so implementiert ist - ich habe es überprüft, es funktioniert - also können Sie es verwenden, wenn die Standard-C++-Syntax entscheidend ist, ist es einfach, die ganze Logik in .dll zu setzen

Документация по MQL5: Стандартная библиотека / Коллекции данных / CArrayObj
Документация по MQL5: Стандартная библиотека / Коллекции данных / CArrayObj
  • www.mql5.com
Класс CArrayObj обеспечивает возможность работы с динамическим массивом указателей на экземпляры класса CObject и его наследников. Это дает возможность работы как с многомерными динамическими массивами примитивных типов данных, так и с более сложно организованными структурами данных. В классе реализованы возможности добавления/вставки/удаления...
 
Andrey Pogoreltsev:

Sie erstellen Kopien von Objekten in AddValue über new, aber Sie geben sie nicht im Destruktor frei, sondern löschen nur die Zeigerliste.

Ach, du liebe Zeit! Und wie kann man eine Instanz einer Klasse löschen, die mit new im Destruktor erstellt wurde. Versuchen Sie, es zu tun. Das wird nicht funktionieren.

Sie können dies nur im Destruktor einer anderen Klasse tun.

 
Nikolai Semko:

Oh, Scheiße! Und wie kann man eine Instanz einer Klasse löschen, die mit new im Destruktor erstellt wurde. Sie können es versuchen. Das wird nicht funktionieren.

Sie können dies nur im Destruktor einer anderen Klasse tun.

Ich habe über den Destruktor einer anderen Klasse gesprochen. Ich sprach von Elementen, die durch new in derAddValue-Methode erstellt wurden

 
Igor Makanu:

Hilfe besagt, dass beim Aufruf eines Destruktors auch die Destruktoren der verwendeten Klassen aufgerufen werden

https://www.mql5.com/ru/docs/standardlibrary/datastructures/carrayobj#carrayobjfeatures

Ich kann mich an keinen Fall erinnern, in dem das Terminal nach dem Entladen des Skripts keine Warnung über nicht zerstörte Objekte in das Protokoll geschrieben hat - mein Beispiel zeigt keine solche Warnung


ich habe von den Entwicklern gehört, dass einfache Strukturen oder Klassen in MQL immer ohne Probleme kopiert werden, ich habe es mehrmals überprüft und es scheint zu stimmen, bisher nutze ich die Möglichkeiten der Sprache


Das ist, worum es in der Diskussion geht - MQL ist nicht C++, ich habe aufgehört, nach Analogien zwischen ihnen zu suchen, die Entwickler haben geschrieben, dass es so implementiert ist - ich habe es überprüft, es funktioniert - also können Sie es verwenden, wenn die Standard-C++-Syntax entscheidend ist, sollte ich mich nicht darum kümmern müssen, die ganze Logik in .dll zu setzen.

Ja, ich habe es in der Hilfe gesehen... Sehr implizite Sache, sieht eher wie eine Krücke aus, anstelle von unique_ptr...

 
Andrey Pogoreltsev:

Ja, ich habe es in der Hilfe gesehen... Sehr implizite Sache, mehr wie eine Krücke anstelle von unique_ptr...

Und es ist so praktisch, dass ich es nicht einmal als Krücke bezeichnen kann:

Erzeugen Sie ein Objekt einer beliebigen Klasse, legen Sie es in einer Speicherliste ab, und Sie müssen sich nicht mehr darum kümmern, es zu entfernen - das Terminal-Subsystem räumt es von selbst auf.
Sie können aber auch den manuellen Betrieb einstellen und für alle neu erstellten Objekte "laufen" lassen, um festzustellen, wann, wo und zu welchem Zweck sie erstellt wurden und ob sie jetzt benötigt werden. Wenn er nicht benötigt wird, löschen Sie ihn. Aber wenn Sie einen Fehler gemacht haben, stellt sich heraus, dass es notwendig war - es stürzt ab, wenn auf einen ungültigen Zeiger zugegriffen wird...

So ist die Krücke nur "jagen Objekte" auf der Suche nach ihrer Nutzlosigkeit und die Sorge um Speicherlecks, wenn einige Objekt nicht aufgeholt worden ist.

 
Andrey Pogoreltsev:

Zweitens ist der korrekte Weg, dies zu tun, über den Kopierkonstruktor, nicht über den Zuweisungsoperator. Aber das ist alles IMHO)

Können Sie mir ein Beispiel dafür geben, wie man es für diese Vorlage richtig kopiert?

template<typename T>class CDataBase
  {
private:
   CList            *mlist;
   T                *Tptr;
public:
   void CDataBase()           { mlist=new CList;                                       }
   void ~CDataBase(void)      { delete mlist;                                          }
   int ArraySize(void)        { return(mlist.Total());                                 }
   T *operator[](int index)   { return(mlist.GetNodeAtIndex(index));                   }
   void  AddValue (T &value)  { Tptr = new T; Tptr  = value; mlist.Add(Tptr);          }
   string TypeName()          { return(typename(T));                                   }
  };

Ich habe Hilfe verwendet, um die AddValue-Methodehttps://www.mql5.com/ru/docs/basis/types/classes zu schreiben.

Ich habe mir das Hirn zermartert, aber ich sehe keine andere Lösung in MQL als die, die ich in meinem Beispiel geschrieben habe!

Zeigen Sie mir Ihre Implementierung der korrekten Datenspeicherung

Документация по MQL5: Основы языка / Типы данных / Структуры, классы и интерфейсы
Документация по MQL5: Основы языка / Типы данных / Структуры, классы и интерфейсы
  • www.mql5.com
Структура является набором элементов произвольного типа (кроме типа void). Таким образом, структура объединяет логически связанные данные разных типов. Объявление структуры Имя структуры нельзя использовать в качестве идентификатора (имени переменной или функции). Следует иметь ввиду, что в MQL5 элементы структуры следуют непосредственно друг...
 
Artyom Trishkin:

Und es ist so praktisch, dass man es nicht einmal als Krücke bezeichnen kann:

Erstellen Sie ein beliebiges Objekt einer beliebigen Klasse, legen Sie es in die Speicherliste, und Sie müssen sich nicht mehr darum kümmern, es zu entfernen - das Terminal-Subsystem bereinigt es von selbst.
Sie können aber auch den manuellen Betrieb einstellen und für alle neu erstellten Objekte einen "Lauf" durchführen, um herauszufinden, wann, wo und für welche Zwecke sie erstellt wurden und ob sie jetzt benötigt werden. Wenn er nicht benötigt wird, löschen Sie ihn. Aber wenn Sie einen Fehler gemacht haben, stellt sich heraus, dass es notwendig war - es stürzt ab, wenn auf einen ungültigen Zeiger zugegriffen wird...

So ist die Krücke nur "jagen Objekte" auf der Suche nach ihrer Nutzlosigkeit und die Sorge um Speicherlecks, wenn einige Objekt nicht aufgeholt worden ist.

Was ich damit meine, ist, dass ein Zeiger, den Sie der Sammlung hinzufügen, auch bei Ihnen bleibt. Das ist der erste Punkt.

Zweitens geht es nicht um Array-Sammlungen und kontinuierliches Lesen; Sie haben ein fragmentiertes System.

Drittens kann niemand garantieren, dass der Zeiger, den Sie übergeben haben, genau dem Sammelobjekt entspricht.
 
Andrey Pogoreltsev:
Der springende Punkt ist, dass ein Zeiger, den Sie der Sammlung hinzufügen, auch bei Ihnen bleibt. Das ist der erste Punkt.

Zweitens geht es nicht um Array-Sammlungen und kontinuierliches Lesen; Sie haben ein fragmentiertes System.

Drittens gibt es keine Garantie, dass Sie einen Zeiger auf das Sammelobjekt übergeben haben.
  1. Ich meinte, dass das automatische Entfernen aller von Ihnen erstellten Objekte durch das Terminal-Subsystem und das Ablegen von Zeigern auf sie in Listen Sie als Krücke bezeichnen, und dass Sie die manuelle Manipulation Ihrer Objekte und das Erstellen von Krücken dafür nicht als Krücke betrachten.
  2. Das war nicht Teil dessen, was Sie in Punkt 1 gesagt haben, und das ist der Hauptgrund für meine Antwort.
  3. Auch das, und zwar aus demselben Grund.
 
Igor Makanu:

Hilfe besagt, dass beim Aufruf des Destruktors auch die Destruktoren der verwendeten Klassen aufgerufen werden

https://www.mql5.com/ru/docs/standardlibrary/datastructures/carrayobj#carrayobjfeatures

Ich kann mich an keinen Fall erinnern, in dem das Terminal nach dem Entladen des Skripts keine Warnung über nicht zerstörte Objekte in das Protokoll geschrieben hat - mein Beispiel zeigt keine solche Warnung


ich habe von den Entwicklern gehört, dass einfache Strukturen oder Klassen in MQL immer ohne Probleme kopiert werden, ich habe es mehrmals überprüft und es scheint zu stimmen, bisher nutze ich die Möglichkeiten der Sprache


Das ist es, worum es in der Diskussion geht - MQL ist nicht C++, ich habe es aufgegeben, nach Analogien zwischen ihnen zu suchen, die Entwickler schrieben, dass es so implementiert ist - ich habe es überprüft, es funktioniert - also können Sie es verwenden, wenn die Standard-C++-Syntax entscheidend ist, können Sie leicht die gesamte Logik in .dll schreiben

Kann man damit eine dreieckige Anordnung herstellen?

 

Aufgrund der sprachlichen Einschränkungen ist es unwahrscheinlich, dass irgendetwas Anständiges funktionieren wird. Ich habe diese Krücke (ein leichtes Wrapper über ein Standard-Array).

#define  GENERATE_VECTOR_GROWTH_FACTOR 2
#define  GENERATE_VECTOR(NAME, REF)                                         \  
   template <typename T>                                                   \
   class NAME                                                              \
   {                                                                       \
      int sz;                                                              \
      bool fail_state;                                                     \
   public:                                                                 \
      T a[];                                                               \
      NAME(): sz(0), fail_state(false) {}                                  \
      bool operator!()const      {return this.fail_state;}                 \
      uint size()const           {return this.sz;}                         \
      void clear()               {this.sz = 0; this.fail_state = false;}   \
      void push_back(T REF value) {                                        \
         if (this.sz == ArraySize(this.a)  &&                              \
             ArrayResize(this.a, this.sz*                                  \
                           GENERATE_VECTOR_GROWTH_FACTOR+1) == -1) {       \
            this.fail_state = true;                                        \
            return;                                                        \
         }                                                                 \
         this.a[this.sz++] = value;                                        \
      }                                                                    \
      void reserve(int new_cap) {                                          \
         if (new_cap > ArraySize(this.a))                                  \
            ArrayResize(this.a, new_cap);                                  \
      }                                                                    \
      void erase(int pos) {                                                \
         if ( ! ArrayRemove(this.a, pos, 1) )                              \
            this.fail_state = true;                                        \
      }                                                                    \
   };
#define  GENERATE_VECTOR_EMPTY
GENERATE_VECTOR(vector_fund, GENERATE_VECTOR_EMPTY);  // для фундаментальных типов
GENERATE_VECTOR(vector_ref, const &);                 // для пользовательских
#undef  GENERATE_VECTOR_EMPTY
#undef  GENERATE_VECTOR_GROWTH_FACTOR

struct S {int a;};
class Q {};
bool f() {
   vector_ref<S> v1;
   vector_fund<int> v2;
   vector_ref<Q> v3;
   
   Q q;
   v3.push_back(q);
   v2.push_back(3);
   v2.a[0] = 5;
   
   return !(!v1 || !v2 || !v3);
}

Um Zeiger zu speichern, schreiben Sie einen unic_ptr-Wrapper (auch wenn Sie keinen vollwertigen bekommen können, aber zumindest auto_ptr). Meiner Meinung nach ist selbst ein solches Primitiv viel praktischer als die Template-Analoga aus std.

Grund der Beschwerde: