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

 

MT5 build 1940

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

void OnStart()
{
A a;

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

Il compile dans les deux cas :

A m_A[2]; // и так

A* m_A[2]; // и так

Dans le premier cas, le résultat est un objet qui n'est pas supprimé (créé nouveau) et une fuite de mémoire.

1 undeleted objects left
1 object of type A left
24 bytes of leaked memory

Ok, je libère manuellement ... et puis le compilateur remarque (soudainement) que le tableau contient des non-pointeurs :"pointeur d'objet attendu".

delete m_A[1]; // Если 'm_A' массив объектов -> object pointer expected

Ok, je le déclare comme un tableau de pointeurs.

A* m_A[2];

Il compile ! C'était une nouvelle pour moi. Alors, les MQL ont-ils des pointeurs ou non ? Parce qu'avec les types intégrés, comme char, int, etc.

'*' - pointer cannot be used

Mais cette fois, ce sera au moment de l'exécution.

m_A[0] =a; // получаем: "invalid pointer access"

Ce qui est logique en principe).

Il y a quelques questions concernant les résultats :

1. A quoi servent ces sous-pointeurs dans MQL, s'ils ne remplissent pas leur fonction principale, comme le font les pointeurs en C/C++ ?

2. Pourquoi devrions-nous jouer avec la suppression, si MT connaît à l'octet près la quantité de mémoire qui a fui et peut la libérer automatiquement ?

 

Lors de la suppression, vous devez vérifier le type de pointeur. Un objet est créé avec new - il doit être supprimé (deuxième dans l'exemple) et l'autre est automatique (premier dans l'exemple), il sera supprimé automatiquement.

 
Dmitry Fedoseev:

Lors de la suppression, vous devez vérifier le type de pointeur. Un objet est créé avec new - il doit être supprimé (deuxième dans l'exemple), et l'autre est automatique (premier dans l'exemple), il sera automatiquement supprimé.

C'est-à-dire que dans le premier cas,m_A[0] ne contiendrapas une copie de l'objet de lapile'a' mais un pointeur detypePOINTER_AUTOMATIC vers cet objet local qui deviendra detypePOINTER_INVALID après la sortie de la fonction (si elle est appelée depuis une autre fonction)?

 
Alors, en général, le problème ressemble à ceci : le compilateur permet à un pointeur de typePOINTER_AUTOMATIC d'être enregistré dans un pointeur de typePOINTER_DYNAMIC, et vice versa.
 
SemenTalonov:

C'est-à-dire que dans le premier cas,m_A[0] ne sera pas une copie de l'objet de lapile'a' mais un pointeur detypePOINTER_AUTOMATIC vers cet objet local qui deviendra detypePOINTER_INVALID après la sortie de la fonction (si elle est appelée depuis une autre fonction)?

Tout peut devenir un INVALIDE, s'il n'est pas utilisé correctement. Le problème n'est pas quePOINTER_INVALID, mais qu'un objet créé automatiquement sera également supprimé automatiquement.

En aucun cas, une copie d'un objet ne peut être créée ici. Un pointeur est juste un pointeur - une variable avec un numéro indiquant où se trouve l'objet, dans ce cas l'objet "a". Ainsi, vous pouvez faire référence à l'objet "a" avec "a", ou vous pouvez le faire avec "m_A[0]", il s'agit d'un seul objet, et non de deux objets différents.

Le principe est simple : vous avez créé l'objet, supprimez-le vous-même. Si vous ne l'avez pas créé, laissez-le tranquille. C'est aussi simple que cela.

 
SemenTalonov:
En général, le problème ressemble à ceci : le compilateur vous permet d'enregistrer un pointeur du typePOINTER_AUTOMATIC vers un pointeur du typePOINTER_DYNAMIC et vice versa.

Vice versa. Un pointeur de typePOINTER_DYNAMIC peut être affecté à un pointeur de typePOINTER_AUTOMATIC. Mais c'est correct et bon - cela ouvre beaucoup de possibilités.

 

Je ne comprends pas ce qui ne va pas ?

Nous prenons un tableau d'objets et assimilons son premier élément à l'objet créé sur la pile. En même temps, sans déclarer l'opérateur de copie ! Il s'agit déjà d'une erreur.

Eh bien, en tenant compte du fait que l'objet est très simple, le constructeur de copie est généré là par défaut. Et le tableau contient une copie de l'objet créé.

Pas de problème avec les questions.

1. Les pointeurs remplissent leur rôle, et personnellement, je ne regrette que les pointeurs vers un tableau.

MQL ne devrait pas supprimer ce qu'il n'a pas marqué. Dmitriy avait raison quand il a dit : "Créez un objet, supprimez-le". Je n'aime pas la pratique du "collecteur d'ordures" en C# où les objets sont supprimés non pas quand je le veux mais quand l'assembleur le veut.

 
Georgiy Merts:

Je ne comprends pas ce qui ne va pas ?

Nous prenons un tableau d'objets et assimilons son premier élément à l'objet créé sur la pile. En même temps, sans déclarer l'opérateur de copie ! Il s'agit déjà d'une erreur.

Eh bien, en tenant compte du fait que l'objet est très simple, le constructeur de copie est généré là par défaut. Et le tableau contient une copie de l'objet créé.

C'est ce que j'attendais d'une copie de... Le constructeur de copie par défaut n'est pas une erreur.

MaisDmitry affirme qu'un nouvel objet sera alloué en mémoire et qu'un pointeur de typePOINTER_AUTOMATIC sera renvoyéet qu' il n'y aura pas de copie.

Chacun comprend les bizarreries de MQL à sa manière).

 
SemenTalonov:

C'est ce que j'attendais de la copie... Le constructeur de copie par défaut n'est pas une erreur.

MaisDmitry dit qu'un nouvel objet sera alloué en mémoire et qu'un pointeur de typePOINTER_AUTOMATIC sera renvoyé.

Chacun comprend les bizarreries de MQL à sa manière).

Que voulez-vous dire par "ce n'est pas une erreur" ? Vous utilisez un opérateur qui n'est pas défini.

Eh bien, vous avez là un objet pratiquement vide, mais que se passe-t-il s'il y a d'autres sous-objets dans cet objet, qui nécessitent une initialisation, et si cet objet lui-même nécessite une demande de ressources ?

Il me semble que vous ne pouvez pas utiliser quelque chose qui n'est pas déclaré.

"Bizarreries" que je n'ai pas vues, je pense que Dimitri a tort à propos de "pas de copie de l'objet" - et la raison, encore une fois, est qu'une déclaration non déclarée est utilisée.

 

D'où vient la copie d'un objet ? Une copie d'un pointeur, oui, mais pointant vers le même objet.

 
Georgiy Merts:

Que voulez-vous dire par "pas d'erreur" ? ?? Vous utilisez un opérateur qui n'est pas défini.

Ce que je veux dire, c'est qu'un constructeur de copie explicitement déclaré ne changerait rien à ce test.

Comment pouvez-vous ne pas voir l'évidence...

Un pointeur va vers un élément d'un tableau d' objets et un objet va vers un élément d'un tableau de pointeurs... est-ce vraiment correct ?

dans le premier cas le tableau devient un pointeur vers un objet dans le second cas le constructeur de copie devrait fonctionner, comment ces opérations peuvent-elles être équivalentes ?