Erreurs, bugs, questions - page 1951

 
fxsaber:
Remplacez-la par une macro.

Ça ne marchera pas. Il s'agit d'une méthode de classe et le paramètre est en fait pris dans l'objet. Je l'ai simplifié ici par exemple.

 
Stanislav Korotky:

Ça ne marchera pas. Il s'agit d'une méthode de classe et le paramètre est en fait pris dans l'objet. Je l'ai simplifié ici par exemple.

Vous feriez mieux de vous familiariser avec la tâche originale, bien sûr...

Serait-ce mal de renvoyer un pointeur ?

 

Stanislav Korotky:

Cela fonctionne, sauf que cela crée une copie interne supplémentaire, et quel'instruction de retour nécessite un constructeur de copie dans la classe. Bien que la copie soit clouée à la sortie de la fonction, j'aimerais éliminer la copie elle-même.


Class function()
{
  int param = 0;
  Class obj(param);
  return obj;
}

Bien sûr, la variable locale est détruite à la sortie de la fonction.
Utilisez new et renvoyez le pointeur, quel est le problème ?

Si vous avez besoin de contrôler les ressources, utilisez un wrapper comme le smart pointer.
Peut-être que vous pourriez utiliser quelque chose de Creational Patterns comme singleton ou builder...

 
fxsaber:

Mieux vaut, bien sûr, se familiariser avec la tâche originale...

Serait-ce une erreur de renvoyer le pointeur ?

C'était à l'origine sur les pointeurs. Mais c'est ensuite au code client qu'il incombe de les supprimer, ce qui représente beaucoup de déchets, sans parler du fait qu'il suffit d'un clin d'œil pour se retrouver avec des liens suspendus.

 
Sergey Dzyublik:

Bien sûr que si, après avoir quitté la fonction, la variable locale est détruite.

Utiliser new et retourner un pointeur, quel est le problème ?

Si vous avez besoin de contrôler les ressources, utilisez un wrapper comme le smart pointer.
Peut-être que quelque chose de Creational Patterns comme singleton ou builder vous conviendra.

Les pointeurs sont là - mais ils ne sont pas pratiques (réponse ci-dessus). J'ai essayé de chercher du côté des "intelligences". Mais j'ai l'impression que pour MQL, un pointeur intelligent ne fera que donner un autre niveau de référentialité, qui devra être contrôlé à son tour. Après tout, qu'est-ce qu'un pointeur intelligent ? - Il s'agit d'un objet enveloppant dans lequel la référence initiale est placée. Et qui et quand nettoiera l'emballage ? ;-) Si vous avez des solutions toutes prêtes, n'hésitez pas à m'en faire part. J'ai un cas d'essai pour le moment.

 
Stanislav Korotky:

Après tout, qu'est-ce qu'un pointeur intelligent ? - Il s'agit d'un objet enveloppant dans lequel la référence originale est placée. Et qui et quand nettoiera l'emballage ? ;-) Si vous avez des solutions toutes prêtes, n'hésitez pas à m'en faire part. J'ai un cas d'essai pour le moment.


Utilisez shared_ptr.
Il n'est pas nécessaire de nettoyer ce wrapper, il suffit de le copier et shared_ptr indique combien d'instances de la ressource désirée restent et quand libérer telle ou telle ressource.


Il n'existe pas de solutions toutes faites, du moins pour moi. Adaptez les C++.

 
Sergey Dzyublik:

Il n'existe pas de solutions toutes faites, du moins pas pour moi. Adaptez les C++.

C'est compréhensible - c'est ce que je fais, mais j'ai déjà l'impression que MQL ne permet pas de faire du "traçage".

 
Stanislav Korotky:

Existe-t-il un moyen de retourner une instance d'objet anonyme à partir d'une fonction ?

Comme quelqu'un l'a déjà souligné ici, la manière la plus correcte est de retourner un pointeur intelligent à partir d'une fonction. Tout cela est mis en œuvre dans MQL. Bien qu'il ne soit pas aussi pratique à utiliser qu'en C++, car le passage par pointeur doit être implémenté via une méthode, plutôt que via l'opérateur pass. D'ailleurs, pour la tâche en question, je suppose que shared_ptr n'est pas nécessaire, unique_ptr sera suffisant.

Sinon, le pointeur créé dans la fonction pourrait être immédiatement placé dans un tableau global, qui serait mis à la poubelle à la fin du programme. En même temps, l'utilisateur peut libérer la mémoire de l'objet à tout moment en appelant une fonction spéciale (pas de suppression). C'est comme CloseHandle dans WinApi.

Cela fonctionne, sauf qu'une copie interne supplémentaire est créée et que l'opérateur de retour nécessite un constructeur de copie dans la classe. Bien que la copie soit clouée lorsque la fonction sort, j'aimerais éliminer la copie elle-même.

Peut-être le compilateur est-il suffisamment intelligent pour optimiser et mettre tout en ligne par lui-même, en excluant toute copie inutile. Mais nous devons le vérifier. Il serait bon que quelqu'un effectue des tests et des mesures. Parce que je me trouve souvent confronté à un tel dilemme, moi aussi.

 
Alexey Navoykov:

Comme quelqu'un l'a déjà souligné, la manière correcte de procéder est de renvoyer un pointeur intelligent à partir d'une fonction. Tout cela est mis en œuvre dans MQL. Mais ce n'est pas aussi pratique à utiliser qu'en C++, car le changement de pointeur doit être implémenté via une méthode, et non via un opérateur de commutation. D'ailleurs, pour la tâche en question, je suppose que shared_ptr n'est pas nécessaire, unique_ptr sera suffisant.

Sinon, le pointeur créé dans la fonction pourrait être immédiatement placé dans un tableau global, qui serait mis à la poubelle à la fin du programme. En même temps, l'utilisateur peut libérer la mémoire de l'objet à tout moment en appelant une fonction spéciale (pas de suppression). C'est comme CloseHandle dans WinApi.

Peut-être le compilateur est-il suffisamment intelligent pour tout optimiser et mettre en ligne tout seul, éliminant ainsi les copies inutiles. Mais nous devons le vérifier. Il serait bon que quelqu'un effectue des tests et des mesures. Sinon, je me retrouve souvent moi aussi face à un tel dilemme.

Je publie mon implémentation ci-dessous - de toute façon ces smart-pointers sont créés temporairement, et en conséquence j'ai créé et cloué plus d'objets que je n'en avais ;-).

Bien sûr, j'ai à l'esprit une variante du tableau global, mais c'est tellement laid ! En particulier parce que je voulais nettoyer par minuterie (parce que le programme peut fonctionner pendant des jours), et la minuterie dans MQL ne peut pas être attachée à une classe/objet - elle ne vient que du gestionnaire global.

Le compilateur n'aide pas ici - testé - l'objet local par retour est dupliqué et ensuite cloué. Il n'y a pas de mouvement optimal dans ce cas.

template<typename T>
class auto_ptr
{
  private:

    class Reference
    {
      public:
        int count;
        Reference(): count(0) {}
    };

    T *data;
    Reference *reference;

    void remove()
    {
      if(reference != NULL)
      {
        reference.count--;
        if(reference.count == 0)
        {
          delete data;
          delete reference;
        }
      }
    }

    
  public:
    auto_ptr(): data(NULL), reference(NULL)
    {
    }
    auto_ptr(T *ptr): data(ptr), reference(ptr == NULL ? NULL : new Reference())
    {
      if(reference != NULL) reference.count++;
    }
    auto_ptr(auto_ptr<T> &ref): data(ref.data), reference(ref.reference)
    {
      reference.count++;
    }
    
    ~auto_ptr()
    {
      remove();
    }
    
    void operator=(auto_ptr<T> &next)
    {
      if(&this != &next)
      {
        remove();
        
        data = next.data;
        reference = next.reference;
        reference.count++;
      }
    }
};
 
Stanislav Korotky:

Le compilateur n'aide pas ici - testé - l'objet local par retour est dupliqué et ensuite cloué. Il n'y a pas de mouvement optimal dans ce cas.


Avez-vous effectué des tests de vitesse ? Ou simplement le diagnostic de la création d'objets? Si c'est le second, alors bien sûr rien ne sera supprimé du code, car vous l'empêchez vous-même avec vos contrôles.