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

 
Ilya Malev:

Ce n'est tout simplement pas la même chose en MCL qu'en C++. Ici, un pointeur n'est pas du tout un type de données distinct, donc les deux sont des objets, et une variable contient son handle.

n'est-ce pas ?

// тот же класс А что был выше

A a; // будет создан автообъект с реальным выделением памяти и инициализацией. 'a' является указателем со статусом POINTER_AUTOMATIC

A* pA; // память под объект не выделена, объекта нет. pA является указателем со статусом POINTER_INVALID или POINTER_DYNAMIC?

Mais je ne peux pas dire avec certitude quel est le statut du pointeur après sa création :POINTER_INVALID ou POINTER_DYNAMIC. En théorie, il devrait être POINTER_INVALID jusqu'à ce qu'il obtienne l'adresse de new.

 
Ilya Malev:

C'est-à-dire, déclarer

Et vous aurez exactement le même "auto-objet", mais vous devrez le supprimer vous-même.

Ce n'est pas auto...

 
SemenTalonov:

Je ne peux pas dire quel statut le pointeur obtient après sa création,POINTER_INVALID ou POINTER_DYNAMIC. En principe, il devrait être POINTER_INVALID jusqu'à ce que new obtienne l'adresse.

C'est exact, l'état sera POINTER_INVALID. Mais les variables a et pA sont du même type. Seul a est une constante, le constructeur est appelé à la création et le destructeur à la sortie du bloc, tandis que pA est accédé aléatoirement et le constructeur et le destructeur sont appelés arbitrairement.

Une variable déclarée sans * ne peut pas obtenir l'état POINTER_INVALID sans astuces particulières, c'est aussi vrai, mais pas parce que les variables sont de types différents, mais parce que le compilateur contrôle bien les appels aux constructeurs et destructeurs, et lui interdit d'attribuer une autre valeur.

Et comme les variables sont essentiellement du même type, il n'y a pas de logique pour accéder différemment aux méthodes de la classe par leur intermédiaire.

 
Ilya Malev:

C'est correct, l'état sera POINTER_INVALID. Mais les variables a et pA sont du même type. Seul a est constant et le constructeur est appelé à la création, et le destructeur à la sortie du bloc, et pA est avec un accès aléatoire, et avec des appels aléatoires du constructeur et du destructeur.

Tout le problème vient donc du fait qu'il faut les distinguer. C'est-à-dire qu'un pointeur exige une attitude plus responsable (laDYNAMIQUE).

 
SemenTalonov:

La seule raison de ce problème est qu'il faut les distinguer. C'est-à-dire qu'un pointeur exige une attitude plus responsable (laDYNAMIQUE).

À mon avis, l'intérêt de la POO est seulement que les références d'objets peuvent être transmises et stockées, et que différentes classes avec un comportement différent peuvent être écrites en elles. En commençant à stocker une référence à un "auto-objet" sans même toucher au polymorphisme, on perd déjà toute leur distinction (puisqu'il n'y a pas de variables utilisateur de type A&)

 
Ilya Malev:

Une variable déclarée sans * ne peut pas recevoir le statut POINTER_INVALID sans astuces particulières, c'est également vrai, mais pas parce que les variables sont de types différents, mais parce que le compilateur contrôle bien les appels aux constructeurs et destructeurs, et interdit de lui attribuer une valeur différente.

Exactement. Le pointeur auto-objet ne changera pas d'état, tandis que le pointeurPOINTER_DYNAMIC peut devenir non valide à tout moment de l'exécution du programme. Les raisons ne sont pas aussi importantes que la possibilité même d'un tel événement.

 
SemenTalonov:

Exactement. Le pointeur d'auto-objet ne changera pas d'état, tandis que le pointeurPOINTER_DYNAMIC peut devenir invalide pendant l'exécution du programme. Les raisons ne sont pas aussi importantes que la possibilité même d'un tel événement.

Il existe un remède excellent et sûr pour cela :

class A{~A(){}};

void OnStart()
 {
  A*a=new A;
  delete a; // oops =))
 };
Eh bien, je pense que les programmeurs devraient surveiller le temps de vie des objets et les façons d'accéder aux variables elles-mêmes, tandis qu'une architecture bien conçue minimisera les erreurs un an ou deux après l'écriture du code...
 
En fait, la durée de vie de l'objet doit correspondre à la durée de vie des pointeurs "vivants" sur celui-ci. Bien sûr, l'objet dynamique POINTER_DYNAMIC est aussi une solution à mi-chemin, qui crée des problèmes pour un codage irréfléchi. Mais POINTER_AUTOMATIC ne me donne pas non plus l'évolutivité dont j'ai besoin pour gérer correctement les objets. Nous avons besoin que ce soit comme ceci - si aucun pointeur vers l'objet n'a été créé en sortant du bloc, sauf l'autovariable dans laquelle il a été créé, alors supprimez l'objet. Si les références ont été reçues en dehors du bloc actuel - ne supprimez pas l'objet tant que ces références existent encore. Ainsi, il y aura de l'évolutivité et le codeur n'aura pas à surveiller la suppression toute seule en permanence... (par exemple, si vous écrivez maintenant A* a = new A ; puis a = new A à nouveau, le premier objet sera perdu à jamais et il est garanti qu'il y aura des erreurs de fuite de mémoire dans les journaux à la sortie du programme. Et où le fameux optimiseur de code regarde-t-il cela).
 
Ilya Malev:
Essentiellement, la durée de vie d'un objet doit correspondre à la durée de vie des pointeurs "vivants" sur cet objet. Bien sûr, l'objet dynamique de type mkl POINTER_DYNAMIC est aussi une solution semi-optionnelle qui pose des problèmes lorsque le codage n'est pas très efficace. Mais POINTER_AUTOMATIC ne me donne pas non plus l'évolutivité dont j'ai besoin pour gérer correctement les objets. Nous avons besoin que ce soit comme ceci - si aucun pointeur vers l'objet n'a été créé en sortant du bloc, sauf l'autovariable où il a été créé, alors supprimez l'objet. Si les références ont été reçues en dehors du bloc actuel - ne supprimez pas l'objet tant que ces références sont encore en vie. Ainsi, il y aura de l'évolutivité et le codeur n'aura pas à surveiller la suppression toute seule en permanence... (par exemple, si vous écrivez maintenant A* a = new A ; puis a = new A à nouveau, le premier objet sera perdu à jamais et il est garanti qu'il y aura des erreurs de fuite de mémoire dans les journaux à la sortie du programme. Et où le célèbre optimiseur de code regarde-t-il cela ?)

C'était une sacrée surprise, aussi. Après tout, il connaît exactement chaque octet qui s'est échappé, mais ne veut pas le libérer. Donc il ne regarde pas du tout les dino-pointeurs pour le moment ? Il compte simplement la différence entre la mémoire demandée et la mémoire libérée à la fin.

Et la durée de vie et les pointeurs vides/perdus ne sont qu'un des problèmes. Avant, nous avons discuté des problèmes liés à la conversion implicite des pointeurs en objets, c'est là qu'il y a un plantage) Lorsque par erreur (par exemple, le compilateur n'a pas dû permettre de compiler un tel code), au lieu du pointeur attendu, vous pouvez obtenir une copie d'un objet par pointeur, qui à son tour peut pointer vers nulle part). Vous avez déjà écrit vous-même sur les opérations de comparaison. Tout y est également très implicite.

 
SemenTalonov:

1. C'était une sacrée surprise, aussi. Après tout, il connaît exactement chaque octet qui s'est échappé et ne veut pas le libérer. Donc il ne regarde pas du tout les dino-pointeurs pour le moment ? Il compte juste la différence entre la mémoire demandée et la mémoire libérée à la fin.

Et la durée de vie et les pointeurs vides/perdus ne sont qu'un des problèmes.

1. Pas vraiment, écrire un simple GC pour les objets dynamiques serait un jeu d'enfant pour les développeurs, mais ils ont laissé ces messages exprès, pour que les codeurs puissent voir qu'ils ont un problème dans leur programme. Parce que leurs objets dynamiques sont un tel semi-C# (je ne suis pas un expert en la matière, mais d'après ce que j'ai entendu) - comme si les objets se comportaient de la même manière (pas de pointeurs, mais tout est objet), et aucun sous-système élaboré pour eux n'a été développé.

2. Eh bien, oui, bien sûr, si les variables d'objet étaient du même type (c'est-à-dire : supprimées non pas automatiquement ou indépendamment, mais par le collecteur de déchets intégré lorsqu'il n'y a plus de références à elles), alors toutes les références à elles seraient exactement les mêmes.

Raison: