Libreria di classi generiche - bug, descrizione, domande, caratteristiche d'uso e suggerimenti - pagina 26

 
Andrey Pogoreltsev:

Si creano copie di oggetti in AddValue tramite new, ma non si rilasciano nel distruttore, si cancella solo la lista dei puntatori.

la guida dice che chiamando un distruttore si chiameranno anche i distruttori delle classi che avete usato

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

Non ricordo un caso in cui il terminale non abbia scritto nel log un avvertimento sugli oggetti non distrutti dopo che lo script è stato scaricato - il mio esempio non mostra tale avvertimento


Andrey Pogoreltsev:

In secondo luogo, avresti dovuto farlo correttamente con il costruttore di copia invece dell'operatore di assegnazione. Ma tutto questo è IMHO)

Ho trovato informazioni da sviluppatori che strutture o classi semplici in MQL sono sempre copiate senza problemi, l'ho controllato diverse volte e sembra essere vero, finché uso le caratteristiche del linguaggio


Questo è ciò che riguarda la discussione - MQL non è C++, ho smesso di cercare analogie tra loro, gli sviluppatori hanno scritto che questo è il modo in cui è implementato - l'ho controllato, funziona - quindi potete usarlo.

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

Si creano copie di oggetti in AddValue tramite new, ma non si liberano nel distruttore, si cancella solo la lista dei puntatori.

Oh, caro! E come si può cancellare un'istanza di una classe creata tramite new nel distruttore. Prova a farlo. Non funzionerà.

Potete farlo solo nel distruttore di qualche altra classe.

 
Nikolai Semko:

Oh, merda! E come si può cancellare un'istanza di una classe creata tramite new nel distruttore. Si può provare. Non funzionerà.

Potete farlo solo nel distruttore di un'altra classe.

Stavo parlando del distruttore di un'altra classe. Stavo parlando di elementi creati tramite new nel metodoAddValue

 
Igor Makanu:

dice che quando il distruttore viene chiamato, anche i distruttori delle classi utilizzate saranno chiamati

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

Non ricordo un caso in cui il terminale non abbia scritto un avviso di oggetti non distrutti nel log dopo che lo script è stato scaricato - il mio esempio non mostra tale avviso


Ho sentito dire dagli sviluppatori che strutture o classi semplici in MQL sono sempre copiate senza problemi, l'ho controllato diverse volte e sembra essere vero, per ora uso le possibilità del linguaggio


Questo è ciò che riguarda la discussione - MQL non è C++, ho smesso di cercare analogie tra loro, gli sviluppatori hanno scritto che questo è il modo in cui è implementato - l'ho controllato, funziona - quindi puoi usarlo, se la sintassi standard C++ è fondamentale, non dovrei preoccuparmi di mettere tutta la logica in .dll.

Sì, l'ho visto nell'aiuto... Una cosa molto implicita, sembra più una stampella, invece di unique_ptr...

 
Andrey Pogoreltsev:

Sì, l'ho visto nell'aiuto... Una cosa molto implicita, più come una stampella invece di unique_ptr...

Ed è così comodo che non posso nemmeno chiamarlo una stampella:

Create un oggetto di qualsiasi classe, mettetelo in una lista di memoria, e non dovrete più preoccuparvi di rimuoverlo - il sottosistema terminale lo pulisce da solo.
Ma si può anche impostare il funzionamento manuale e "eseguire" per tutti gli oggetti appena creati cercando di tracciare quando, dove e per quali scopi è stato creato e se è necessario ora. Se non è necessario, cancellatelo. Ma quando hai fatto un errore, si scopre che era necessario - si blocca quando si accede a un puntatore non valido...

Quindi la stampella è solo "inseguire gli oggetti" cercando la loro inutilità e preoccupandosi delle perdite di memoria se qualche oggetto non è stato raggiunto.

 
Andrey Pogoreltsev:

In secondo luogo, la cosa giusta da fare è usare il costruttore di copia invece dell'operatore di assegnazione. Ma questo è tutto IMHO)

Puoi darmi un esempio di come copiarlo correttamente per questo modello?

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));                                   }
  };

Ho usato l'aiuto per scrivere il metodo AddValuehttps://www.mql5.com/ru/docs/basis/types/classes

Mi sono scervellato, ma non vedo altra soluzione in MQL che quella che ho scritto nel mio esempio!

Mostrami la tua implementazione della corretta memorizzazione dei dati

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

Ed è così comodo che non si può nemmeno chiamarlo stampella:

Create qualsiasi oggetto di qualsiasi classe, mettetelo nella lista di memoria e non dovrete più preoccuparvi di rimuoverlo - il sottosistema terminale lo pulisce da solo.
Ma si può anche impostare il funzionamento manuale ed "eseguire" per tutti gli oggetti appena creati cercando di scoprire quando, dove e per quali scopi è stato creato e se è necessario ora. Se non è necessario, cancellatelo. Ma quando hai fatto un errore, si scopre che era necessario - si blocca quando si accede a un puntatore non valido...

Quindi la stampella è solo "inseguire gli oggetti" cercando la loro inutilità e preoccupandosi delle perdite di memoria se qualche oggetto non è stato raggiunto.

Quello che voglio dire qui è che quando si aggiunge un puntatore alla collezione, questo rimane anche con voi. Questa è la prima cosa.

In secondo luogo, non stiamo parlando di arrays-collections e lettura continua; avete un sistema frammentato.

In terzo luogo, non potete garantire di aver passato un puntatore a un oggetto della collezione.
 
Andrey Pogoreltsev:
Il punto qui è che una volta che aggiungete un puntatore alla collezione, rimane anche con voi. Questo è il primo.

In secondo luogo, non stiamo parlando di arrays-collections e lettura continua; avete un sistema frammentato.

In terzo luogo, nessuno garantisce che avete passato un puntatore all'oggetto della collezione.
  1. Intendevo dire che la rimozione automatica da parte del sottosistema terminale di tutti i vostri oggetti creati e mettere i puntatori ad essi nelle liste la chiamate stampella, e non considerate la manipolazione manuale dei vostri oggetti e la creazione di stampelle per essa una stampella.
  2. Questo non faceva parte di quello che hai detto al punto 1, ed è la ragione principale per cui ho risposto.
  3. Anche questo, e per la stessa ragione.
 
Igor Makanu:

dice che quando il distruttore viene chiamato, anche i distruttori delle classi utilizzate saranno chiamati

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

Non ricordo un caso in cui il terminale non abbia scritto un avviso di oggetti non distrutti nel log dopo che lo script è stato scaricato - il mio esempio non mostra tale avviso


Ho sentito dire dagli sviluppatori che strutture o classi semplici in MQL sono sempre copiate senza problemi, l'ho controllato diverse volte e sembra essere vero, per ora uso le possibilità del linguaggio


Questo è ciò che riguarda la discussione - MQL non è C++, ho rinunciato a cercare analogie tra loro, gli sviluppatori hanno scritto che questo è il modo in cui è implementato - l'ho controllato, funziona - quindi potete usarlo, se la sintassi standard C++ è cruciale, potete facilmente scrivere tutta la logica in .dll

Si può fare un array triangolare con questo?

 

A causa delle limitazioni della lingua, è improbabile che qualcosa di decente funzioni. Ho questa stampella (un wrapper leggero su un array standard).

#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);
}

Per memorizzare i puntatori, scrivete un wrapper unic_ptr (anche se non potete averne uno completo, ma almeno auto_ptr). A mio parere, anche una tale primitiva è molto più conveniente delle controparti template di std.