Biblioteca de classes genéricas - bugs, descrição, perguntas, recursos de uso e sugestões - página 26

 
Andrey Pogoreltsev:

Cria-se cópias de objectos em AddValue através do novo, mas não se liberta no destruidor, apenas se limpa a lista de apontadores.

a ajuda diz que quando se chama um destruidor, os destruidores das classes que usou também serão chamados

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

Não me lembro de um caso em que o terminal não tenha escrito no registo um aviso sobre objectos não destruídos depois de o guião ter sido descarregado - o meu exemplo não mostra tal aviso


Andrey Pogoreltsev:

Em segundo lugar, deveria tê-lo feito correctamente com o construtor de cópias em vez do operador de atribuição. Mas tudo isto é IMHO)

Encontrei informação dos programadores de que estruturas ou classes simples em MQL são sempre copiadas sem problemas, verifiquei-a várias vezes e parece ser verdade, até usar as características da linguagem


É disto que se trata a discussão - MQL não é C++, deixei de procurar analogias entre eles, os programadores escreveram que é assim que é implementado - eu verifiquei, funciona - para que possa usá-lo, se a sintaxe padrão C++ é crucial, pode facilmente escrever toda a lógica em .dll

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

Cria cópias de objectos em AddValue através de novos, mas não os liberta no destruidor, apenas limpa a lista de apontadores.

Oh, meu Deus! E como se pode apagar uma instância de uma classe criada através de novo no destruidor. Tente fazer isso. Não vai funcionar.

Só o pode fazer no destruidor de alguma outra classe.

 
Nikolai Semko:

Oh, merda! E como se pode apagar uma instância de uma classe criada através de novo no destruidor. Pode experimentá-lo. Não vai funcionar.

Só o pode fazer no destruidor de outra classe.

Eu estava a falar do destruidor de outra classe. Estava a falar de artigos criados através do novo métodoAddValue

 
Igor Makanu:

a ajuda diz que quando um destruidor é chamado, os destruidores das classes utilizadas também serão chamados

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

não me lembro de um caso em que o terminal não tenha escrito um aviso sobre objectos não destruídos no registo depois de o guião ter sido descarregado - o meu exemplo não mostra tal aviso


ouvi dos criadores que estruturas ou classes simples em MQL são sempre copiadas sem qualquer problema, verifiquei-o várias vezes e parece ser verdade, até agora utilizo as possibilidades da linguagem


É disto que se trata a discussão - MQL não é C++, deixei de procurar analogias entre eles, os programadores escreveram que é assim que é implementado - eu verifiquei, funciona - para que se possa usá-lo, se a sintaxe padrão C++ é crucial, não deveria ter de me preocupar em colocar toda a lógica em .dll.

Sim, vi-o na ajuda... Muito implícito, parece mais uma muleta, em vez de um único_ptr...

 
Andrey Pogoreltsev:

Sim, vi-o na ajuda... Muito implícito, mais como uma muleta, em vez de um único_ptr...

E é tão útil que nem lhe posso chamar uma muleta:

Crie um objecto de qualquer classe, coloque-o numa lista de armazenamento, e não tem de se preocupar mais em removê-lo - o subsistema terminal limpa-o por si só.
Mas também se pode definir a operação manual e "correr" para todos os objectos recém-criados tentando localizar quando, onde e para que fins foi criado e se é necessário agora. Se não for necessário, apagá-lo. Mas quando se comete um erro, acontece que era necessário - cai quando se acede a um ponteiro inválido...

Assim, a muleta é apenas "perseguir objectos" à procura da sua inutilidade e preocupar-se com fugas de memória se algum objecto não tiver sido apanhado.

 
Andrey Pogoreltsev:

Em segundo lugar, a forma correcta de o fazer é através de um construtor de cópias, e não de um operador de cessão. Mas isto é tudo IMHO)

Pode dar-me um exemplo de como copiá-lo correctamente para este modelo?

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

Usei ajuda para escrever o método AddValuehttps://www.mql5.com/ru/docs/basis/types/classes

Eu esmaguei o meu cérebro, mas não vejo nenhuma outra solução em MQL além daquela que escrevi no meu exemplo!

Mostre-me a sua implementação do correcto armazenamento de dados

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

E é tão útil que nem se pode chamar-lhe muleta:

Crie qualquer objecto de qualquer classe, coloque-o na lista de armazenamento, e não tem de se preocupar mais em removê-lo - o subsistema terminal limpa-o por si só.
Mas também se pode definir a operação manual e "correr" para todos os objectos recentemente criados, tentando descobrir quando, onde e para que fins foi criado e se é necessário agora. Se não for necessário, apagá-lo. Mas quando se comete um erro, acontece que era necessário - cai quando se acede a um ponteiro inválido...

Assim, a muleta é apenas "perseguir objectos" à procura da sua inutilidade e preocupar-se com fugas de memória se algum objecto não tiver sido apanhado.

O que quero dizer aqui é que quando se adiciona um ponteiro à colecção, este também fica consigo. Isto é a primeira coisa.

Segundo, não estamos a falar de colecções de arrays e leitura contínua; tem um sistema fragmentado.

Em terceiro lugar, ninguém pode garantir que o ponteiro que passou exactamente para o objecto de colecção.
 
Andrey Pogoreltsev:
A questão aqui é que, uma vez adicionado um ponteiro à colecção, ela também fica consigo. Isso é a primeira coisa.

Em segundo lugar, não estamos a falar de colecções de arrays e de leitura contínua; tem um sistema fragmentado.

Terceiro, ninguém garante que passou um ponteiro para o objecto de colecção.
  1. Referia-me à remoção automática pelo subsistema terminal de todos os seus objectos criados e colocar apontadores para eles em listas a que chama muleta, e não considera a manipulação manual dos seus objectos e a criação de muletas para ela uma muleta.
  2. Isso não fazia parte do que disse no ponto 1, e é a principal razão pela qual eu respondi.
  3. Isso também, e pela mesma razão.
 
Igor Makanu:

a ajuda diz que quando o destruidor é chamado, os destruidores das classes utilizadas também serão chamados

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

não me lembro de um caso em que o terminal não tenha escrito um aviso sobre objectos não destruídos no registo depois de o guião ter sido descarregado - o meu exemplo não mostra tal aviso


ouvi dos criadores que estruturas ou classes simples em MQL são sempre copiadas sem qualquer problema, verifiquei-o várias vezes e parece ser verdade, até agora utilizo as possibilidades da linguagem


É disto que se trata a discussão - MQL não é C++, desisti de procurar analogias entre eles, os programadores escreveram que é assim que é implementado - eu verifiquei, funciona - para que possa usá-lo, se a sintaxe padrão C++ é crucial, pode facilmente escrever toda a lógica em .dll

Pode ser feita uma matriz triangular com isto?

 

Devido a limitações linguísticas, é pouco provável que algo decente funcione. Tenho esta muleta (um invólucro leve sobre uma matriz padrão).

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

Para guardar indicações, escreva um invólucro unic_ptr (embora não possa obter um completo, mas pelo menos auto_ptr). Na minha opinião, mesmo este primitivo é muito mais conveniente do que o modelo de contrapartidas da std.

Razão: