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

 
Le signe = copie la zone de mémoire d'un objet dans la zone de mémoire d'un autre objet. Tous les objets restent là où ils étaient.
 
Vladimir Simakov:
Il n'y a aucun moyen de le déclencher. C'est une pure fuite de mémoire.

Faites en sorte qu'il puisse être invoqué.

 

Au fait, messieurs les développeurs, nous ferions mieux de réparer ça. Après tout, new renvoie un pointeur, alors ajoutez une vérification qu'à l'autre bout = aussi un pointeur, supprimez la conversion implicite (A) new A() ; comme je le comprends - c'est ce qui se passe.

 
Vladimir Simakov:

Au fait, chers développeurs, je ferais mieux de réparer ça. Après tout, new renvoie réellement un pointeur, donc ajoutez une vérification que l'autre extrémité = également un pointeur, supprimez la conversion implicite (A) new A() ; comme je l'ai compris - c'est ce qui se passe.

Il y a un appel pour cet opérateur

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

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

fxsaber, 2019.01.10 06:36

Depuis quand sont-ils définis (question pour les 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;    


Grosso modo, cela ressemble à ceci

class A
{
public:
    int iValue;
    
    void operator =( const A* Ptr )
    {
      Print(__FUNCSIG__);
      
      this.iValue = Ptr.iValue;
    }
};
//......................
A m_A[2];

void OnStart()
{
A a;

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

L'appel à cet opérateur s'arrête là


Grosso modo, cela ressemble à ceci

Oui, j'ai compris. Ce n'est pas un mauvais râteau. Au fait, cette surcharge de l'opérateur = n'existe pas en C++, jure VS.
 

Avant de faire des histoires, il serait bon de savoir qu'en MQL, les pointeurs ont toujours été implicitement convertis en objets (déréférencés), c'est pratique et tout le monde s'y est habitué. Au lieu d'un a()->b()->c()->d() difficile à lire, vous pouvez écrire dans le format habituel de la POO : a().b().c().d(), et faire moins de transformations inutiles en passant aux fonctions. Et maintenant, à cause du mécontentement de quelqu'un, vous changez tout ?

 
Alexey Navoykov:

Avant d'en faire tout un plat, il serait bon de savoir qu'en MQL, les pointeurs ont toujours été convertis en objets implicitement (déréférencés), c'est pratique et tout le monde s'y est habitué. Au lieu d'un a()->b()->c()->d() difficile à lire, vous pouvez écrire dans le format habituel de la POO : a().b().c().d(), et faire moins de transformations inutiles en passant aux fonctions. Et maintenant, à cause du mécontentement de quelqu'un, vous changez tout ?

Ce n'est pas une question de casting. Tu n'y es pas allé.

 

Si nous sommes guidés par le prototype déclaré de MQL - C++.

En C++, l'opérateur new renvoie un pointeur, respectivement, si m_A est un tableau d'objets :

m_A[1] = new A();

il y aurait une erreur de type ici.

C'est la ligne que le compilateur aurait sautée :

m_A[1] = *( new A() );

Mais cela provoquerait une fuite de mémoire.


Ce serait bien si MQL avait le même comportement.

 
Alexey Navoykov:

Avant de commencer à faire des histoires à ce sujet, vous devez savoir que dans MQL, les pointeurs ont toujours été implicitement convertis en objets (déréférencés), c'est pratique et tout le monde s'y est habitué. Au lieu d'un a()->b()->c()->d() difficile à lire, vous pouvez écrire dans le format habituel de la POO : a().b().c().d(), et faire moins de transformations inutiles en passant aux fonctions. Et maintenant, à cause du mécontentement de quelqu'un, vous changez tout ?

Et si vous entrez dans les détails avec quelques exemples simples.

A a;

// 'a' ожидает объект
 
a = new A(); // а ему дают указатель, ведь можно же

// что в MQL равнозначно?
a = *(A*) new A();

Par conséquent, nous avons

1. a' obtient une copie de l'objet créé, le pointeur vers le nouvel objet créé est perdu.

2) Qu'arrivera-t-il à 'a' si new ne parvient pas à créer/allouer un objet en mémoire ?

Le deuxième cas (au contraire)

A* a; // глобальный указатель - 'a' ожидает указатель на объект

// далее всё происходит внутри некой функции
A b; // создаем второй в стеке (ну типа в стеке, не суть)

a =b;
// т.е. тут объект "неявно кастится" к указателю?)
a = &b;

1. après avoir quitté la fonction, l'objet 'b' doit être détruit comme un objet local.

à quoi fera référence le "a" alors ?

2. ou l'opérateur de copie fonctionnera-t-il toujours et 'b' sera copié par le pointeur 'a' ? et si 'a' n'a pas été défini auparavant ?

 
SemenTalonov:

Le deuxième cas (au contraire)

A* a; // глобальный указатель - 'a' ожидает указатель на объект

// далее всё происходит внутри некой функции
A b; // создаем второй в стеке (ну типа в стеке, не суть)

a =b;
// т.е. тут объект "неявно кастится" к указателю?)


Ici, c'est l'inverse - un pointeur a est implicitement casté vers un objet (déréférencé), puis operator= lui est appliqué. fxsaber l'a également mentionné hier.

Bien que logiquement cela ne contredise pas les règles MQL (puisque l'appel à operator= est équivalent à l'appel à toute autre méthode d'objet), cela conduit à une compréhension ambiguë de ce code et à des erreurs difficiles à trouver. Et cela ne concerne pas seulement l'opérateur= mais aussi == et !=, au moins. Peut-être qu'un tel casting devrait être interdit pour d'autres opérateurs également, car en C++ vous pouvez appliquer aux opérateurs : +-<>[].

Le verdict est le suivant : lorsque vous appliquez à un pointeur des opérateurs autorisés pour les pointeurs en C++, vous n'autorisez pas le transfert implicite de ce pointeur vers un objet. En conséquence, l'exemple ci-dessus entraînerait une erreur de compilation.