Errori, bug, domande - pagina 1951

 
Stanislav Korotky:

C'è un modo per restituire un'istanza di un oggetto anonimo da una funzione?

Sostituiscilo con una macro.
 
fxsaber:
Sostituiscilo con una macro.

Non funzionerà. Questo è un metodo di classe e il parametro è effettivamente preso dall'oggetto. L'ho semplificato qui per esempio.

 
Stanislav Korotky:

Non funzionerà. Questo è un metodo di classe e il parametro è effettivamente preso dall'oggetto. L'ho semplificato qui per esempio.

È meglio che familiarizziate con il compito originale, naturalmente...

Sarebbe sbagliato restituire un puntatore?

 

Stanislav Korotky:

Funziona, eccetto che crea una copia interna extra, ela dichiarazione di ritorno richiede un costruttore di copia nella classe. Anche se la copia è inchiodata quando la funzione esce, vorrei eliminare la copia stessa.


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

Certo che lo fa, la variabile locale viene distrutta quando la funzione esce.
Usare new e restituire il puntatore, qual è il problema?

Se avete bisogno del controllo delle risorse, usate un wrapper come il puntatore intelligente.
Forse potresti usare qualcosa di Creational Patterns come singleton o builder...

 
fxsaber:

Meglio, naturalmente, familiarizzare con il compito originale...

Sarebbe sbagliato restituire il puntatore?

Questo era originariamente sui puntatori. Ma poi il codice del client è responsabile della loro rimozione, e questo è un sacco di spazzatura, per non parlare del fatto che ci vuole un battito di ciglia e ci si ritrova con dei link sospesi.

 
Sergey Dzyublik:

Certo che lo fa, dopo l'uscita dalla funzione la variabile locale viene distrutta.

Usare new e restituire un puntatore, qual è il problema?

Se avete bisogno del controllo delle risorse, usate un wrapper come il puntatore intelligente.
Forse qualcosa di Creational Patterns come singleton o builder funzionerà per voi.

I puntatori sono lì - scomodi (risposto sopra). Ho provato a guardare verso "l'intelligenza". Ma la mia impressione è che per MQL un puntatore intelligente darà solo un altro livello di referenzialità, che dovrà essere controllato a sua volta. Dopo tutto, cos'è un puntatore intelligente? - È un oggetto wrapper in cui viene messo il riferimento iniziale. E chi e quando pulirà l'involucro? ;-) Se avete soluzioni pronte, per favore scrivetemi. Per ora ho un caso di prova.

 
Stanislav Korotky:

Dopo tutto, cos'è un puntatore intelligente? - È un oggetto wrapper in cui viene inserito il riferimento originale. E chi e quando pulirà l'involucro? ;-) Se avete soluzioni pronte, per favore scrivetemi. Per ora ho un caso di prova.


Usare shared_ptr.
Non è necessario pulire questo wrapper, basta copiarlo e shared_ptr indica quante istanze della risorsa desiderata sono rimaste e quando rilasciare questa o quella risorsa.


Non ci sono soluzioni preconfezionate, almeno per me. Adattare quelli di C++.

 
Sergey Dzyublik:

Non ci sono soluzioni preconfezionate, almeno non per me. Adattare quelli del C++.

È comprensibile - è quello che sto facendo, ma ho già l'impressione che MQL non permetta di fare "tracing".

 
Stanislav Korotky:

C'è un modo per restituire un'istanza di un oggetto anonimo da una funzione?

Come qualcuno ha già sottolineato qui, il modo più corretto è quello di restituire un puntatore intelligente da una funzione. Tutto questo è implementato in MQL. Anche se non è così comodo da usare come in C++, perché il passaggio per puntatore dovrebbe essere implementato tramite metodo, piuttosto che tramite l'operatore pass. A proposito, per il compito in questione suppongo che shared_ptr non sia necessario, unique_ptr sarà sufficiente.

In alternativa, il puntatore creato all'interno della funzione potrebbe essere immediatamente collocato in qualche array globale, che verrebbe cestinato alla fine del programma. Allo stesso tempo, l'utente può liberare la memoria dell'oggetto in qualsiasi momento chiamando una funzione speciale (non cancellare). È come CloseHandle in WinApi.

Funziona, tranne che viene creata una copia interna extra e l'operatore di ritorno richiede un costruttore di copia nella classe. Anche se la copia è inchiodata quando la funzione esce, vorrei eliminare la copia stessa.

Forse il compilatore è abbastanza intelligente da ottimizzare e inlineare tutto da solo, escludendo la copia inutile. Ma dobbiamo controllare. Sarebbe bello se qualcuno conducesse test e misurazioni. Perché anch'io mi trovo spesso di fronte a un simile dilemma.

 
Alexey Navoykov:

Come qualcuno ha già sottolineato, il modo corretto di farlo è restituire un puntatore intelligente da una funzione. Tutto questo è implementato in MQL. Ma non è così comodo da usare come in C++, perché lo switch del puntatore deve essere implementato tramite metodo, non tramite operatore switch. A proposito, per il compito in questione suppongo che shared_ptr non sia necessario, unique_ptr sarà sufficiente.

In alternativa, il puntatore creato all'interno della funzione potrebbe essere immediatamente collocato in qualche array globale, che verrebbe cestinato alla fine del programma. Allo stesso tempo, l'utente può liberare la memoria dell'oggetto in qualsiasi momento chiamando una funzione speciale (non cancellare). È come CloseHandle in WinApi.

Forse il compilatore è abbastanza intelligente da ottimizzare tutto e inlineare tutto da solo, eliminando la copia inutile. Ma dobbiamo controllare. Sarebbe bello se qualcuno facesse dei test e delle misurazioni. Altrimenti mi trovo spesso anch'io di fronte a un simile dilemma.

Sto pubblicando la mia implementazione qui sotto - comunque questi smart-pointers sono creati temporaneamente, e come risultato ho creato e inchiodato più oggetti di quanti ne avessi ;-).

Certo, ho in mente una variante di array globale, ma è così brutto! Soprattutto perché volevo pulire dal timer (perché il programma può andare avanti per giorni), e il timer in MQL non può essere attaccato a una classe/oggetto - viene solo dal gestore globale.

Il compilatore non aiuta qui - testato - l'oggetto locale di ritorno viene duplicato e poi inchiodato. Non esiste una mossa ottimale in questo caso.

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++;
      }
    }
};