MQL5 Le compilateur ne fait pas la distinction entre une classe et un pointeur vers celle-ci - page 3

 
SemenTalonov:

Bingo !

SemenTalonov2019.01.10 07:36POINTER_AUTOMATICet vice versa.

Pas tout à fait un bingo. Pour les objets simples, l'affectation avec l'opérateur = fonctionne. Ce n'est pas un bug, c'est sûr.

 
SemenTalonov:

...

SemenTalonov2019.01.10 07:36POINTER_AUTOMATIC dans un pointeur de typePOINTER_DYNAMIC et vice versa.

Non. Quand il ne s'agit pas d'assigner un pointeur à l'automatique, il s'agit de copier un objet - les valeurs de ses champs, mais seulement avec des objets simples.

 

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégie

Le compilateur MQL5 ne fait pas de distinction entre une classe et un pointeur.

SemenTalonov, 2019.01.10 04:18

class A
{
public:
    int iValue;
};
//......................
A m_A[2];

void OnStart()
{
A a;

    m_A[0] =a; 
    m_A[1] = new A();
}


Depuis quand sont-ils définis (question aux développeurs)

void A::operator =( const A& );
void A::operator =( const A* );

et comment fonctionnent-ils ? Le code compilé suivant semble délirant

    A* b = NULL;    
    m_A[1] = b;    


Et ici, la situation n'est pas claire

A* m_A[2];

void OnStart()
{
A a;

    m_A[0] =a;  // Почему это работает?
    m_A[0] =&a; // Когда должно работать только это?
}
 
Dmitry Fedoseev:

Pas vraiment un bingo. Pour les objets simples, l'affectation avec l'opérateur = fonctionne. Ce n'est pas un bug, c'est sûr.

C'est vrai, c'est le point le plus important.

Personnellement, je pense que l'on ne peut pas utiliser un opérateur d'affectation pour des objets si cet opérateur n'est pas explicitement défini, même si les objets sont simples. Nous pouvons encore nous mettre d'accord sur l'attribution de structures simples. Mais les classes dans lesquelles le constructeur est nécessairement appelé (au moins implicitement) - ne peuvent être assignées que par des opérateurs explicitement définis.

À mon avis, cela a été fait pour faciliter la vie des nouveaux venus.

 
Georgiy Merts:

C'est vrai, c'est le point le plus important.

Personnellement, je pense que l'on ne peut pas utiliser un opérateur d'affectation pour des objets si cet opérateur n'est pas explicitement défini, même si les objets sont simples. Nous pouvons nous mettre d'accord sur l'attribution de structures simples. Mais les classes où le constructeur est nécessairement appelé (au moins, implicitement) - ne peuvent être assignées qu'avec des opérateurs explicitement définis.

À mon avis, cela a été fait pour faciliter la vie des débutants.

Et les complexes sont pratiques - sans eux, vous ne pouvez pas renvoyer MqlTradeRequest, par exemple. Et dans les structures, un constructeur est aussi nécessairement appelé.

 

Il existe une théorie selon laquelle MQL est un C# très dépouillé. Il est donc compréhensible que le compilateur MQL se comporte dans ce cas. Après tout, les classes en C# sont toujours placées dans le tas, donc :

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
class A
{
public:
    int iValue;
};
//......................
A m_A[2];

void OnStart()
{
    // Разместили A в куче, указатель на A передали в m_A[1]
    m_A[1] = new A();
    // Разместили A на стеке...
    A a;
    // А вот фиг вам! ля-ля-ля;) Там вам не тут. 'a' - класс и размещается в куче. Указатель на него передается внутреннему сборщику мусора
    // А раз так, то теперь он AUTOMATIC и к нему нельзя применить delete, т.к. внутренний сборщик мусора его удалит сам 
    
    // скопировали указатель a в массив
    m_A[0] = a;
}
//+------------------------------------------------------------------+

Maintenant, occupons-nous du tableau m_A. Comme m_A est un tableau de classes et que les classes sont toujours placées dans le tas, il n'est pas nécessaire de préciser si le tableau m_A est un tableau de pointeurs ou un tableau d'objets eux-mêmes, car seule la première variante fonctionne toujours pour les classes. Comme m_A est toujours un tableau de pointeurs, MQL n'a pas à préciser s'il stocke des types de référence ou des types significatifs. Donc, A* m_A[2] == A m_A[2]. Amen.

 
Vasiliy Sokolov:

Il existe une théorie selon laquelle MQL est un C# très dépouillé. Il est donc compréhensible que le compilateur MQL se comporte dans ce cas. Après tout, les classes en C# sont toujours placées dans le tas, donc :

Maintenant, occupons-nous du tableau m_A. Comme m_A est un tableau de classes et que les classes sont toujours placées dans le tas, il n'est pas nécessaire de préciser si le tableau m_A est un tableau de pointeurs ou un tableau d'objets eux-mêmes, car seule la première variante fonctionne toujours pour les classes. Comme m_A est toujours un tableau de pointeurs, MQL n'a pas à préciser s'il stocke des types de référence ou des types significatifs. Donc, A* m_A[2] == A m_A[2]. Amen.

Conclusion incorrecte. m_A est un tableau d'objets, pas un pointeur. Et ces objets sont complètement détruits. Ce n'est pas le nouveau A qui est détruit.

class A
{
public:
    int iValue;
    
  ~A()
  {
    Print(__FUNCSIG__);
  }
};
//......................
A m_A[2];

void OnStart()
{
A a;
A* b = new A;

    m_A[0] =a;  // копирование объекта, а не указателя
    m_A[1] = b; // копирование объекта, а не указателя
    
  // по выходу уничтожится три объекта
  delete b; // а так - четыре.
}
 
fxsaber:

Sortie incorrecte. m_A est un tableau d'objets, pas un pointeur. Et ces objets sont complètement détruits. Ce n'est pas le nouveau A qui est détruit.

C'est un bon exemple. Eh bien, réfléchissons davantage.

 

Pfft)) Je suis choqué par cela.

A m_A[2];

void OnStart()
{
A a;
A* b = new A();

    printf("SizeOf 'a' object: %i SizeOf pointer 'b' to object: %i", sizeof(a), sizeof(b));
    
    a =b;
    b =a;
    
    m_A[0] = a;
    m_A[1] = b;
}
SizeOf 'a' object: 20 SizeOf pointer to 'b' object: 8
 
SemenTalonov:

Ouf)) Je suis réellement choqué par cela.

Qu'est-ce qu'il y a de mal à ça ? Dans un cas, un objet, dans l'autre cas, un pointeur.

Raison: