Errori, bug, domande - pagina 2471

 
Igor Makanu:

Spiega perché quando creo CChartObjectLabel non sto cancellando gli oggetti nell'indicatore quando deinizializzo in questo codice:

quando cambio TF ottengo la voce del diario: 2019.05.23 09:49:02.044 tstlabel EURUSD,M30: 2 oggetti di tipo CChartObjectLabel rimasti

se si decommenta in OnInit() la creazione di etichette di testo (CChartObjectLabel), allora tutto funzionerà correttamente

Passo un puntatore alla funzioneCreateLabel(), manon possocancellarlo dopo inOnDeinit()

Crea un nuovo oggetto l. E non viene cancellato.
 
Artyom Trishkin:
Viene creato un nuovo oggetto l. E non viene cancellato.

logicamente

Ma lo scopo delle variabiliCChartObjectLabel *LabelUP,*LabelDN; è globale?

Quindi posso modificare la variabile in qualsiasi punto del codice?

Passo un puntatore alla funzione CreateLabel(), perché creo una nuova copia?

imho, non funziona correttamente.

HH: se creo oggetti in OnInit() e poi lavoro con loro in CreateLabel() (cioè, creo gli oggetti separatamente e lavoro con loro tramite puntatore), tutto funziona correttamente - ma non ricordo un caso in altri compilatori di passare un puntatore a una funzione per creare un nuovo oggetto - un puntatore, è un puntatore!

 
Igor Makanu:

logicamente

ma il mio scopo è globale? - significa che posso modificare una variabile in qualsiasi parte del mio codice?

Passo un puntatore a CreateLabel(), perché ottengo una nuova copia?

Imho, non funziona correttamente.

Riassegnando un puntatore a un nuovo oggetto, si perde l'oggetto precedente a cui puntava il puntatore riassegnato.
 
Igor Makanu:

logicamente

Ma lo scopo delle variabiliCChartObjectLabel *LabelUP,*LabelDN; è globale?

Quindi posso modificare la variabile in qualsiasi punto del codice?

Passo un puntatore alla funzione CreateLabel(), perché creo una nuova copia?

Imho, non funziona correttamente

nuovo deve essere rimosso. Ci sono già oggetti e puntatori ad essi.
 
Artyom Trishkin:
Riassegnando un puntatore a un nuovo oggetto, si perde l'oggetto precedente, che era puntato dal puntatore riassegnato.

no, un puntatore è un puntatore, in MQL è un descrittore, non il punto - ma non è corretto creare una nuova copia dell'oggetto, questo funziona correttamente ora:

//+------------------------------------------------------------------+
//|                                                         test.mq4 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com/ru/users/igorm"
#property version   "1.00"
#property strict
#property indicator_separate_window
#include <ChartObjects\ChartObjectsTxtControls.mqh>
CChartObjectLabel *LabelUP,*LabelDN;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   LabelUP=new CChartObjectLabel;
   LabelDN=new CChartObjectLabel;
   SetLabel(LabelUP,"LabelUP",0);
   SetLabel(LabelDN,"LabelDN",25);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   delete LabelUP;
   delete LabelDN;
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   return(rates_total);

  }
//+------------------------------------------------------------------+
void SetLabel(CChartObjectLabel *l,string name,int y)
  {
   l.Create(0,name,ChartWindowFind(),0,y);
   l.Color(clrYellow);
   l.FontSize(14);
   l.Description(name);
  }
//+------------------------------------------------------------------+

ma se seguite la vostra logica, allora questo codice creerà anche una copia dell'oggetto l nella funzione SetLabel() - ho passato un puntatore, non un riferimento?


Artyom Trishkin:
nuovo dovrebbe essere rimosso. Gli oggetti esistono già e anche i puntatori ad essi.

la domanda non è come risolvere il problema, ma perché nell'ambito globale della variabileCChartObjectLabel *LabelUP,*LabelDN;- ha perso il puntatore!

 
Igor Makanu:

no, un puntatore è un puntatore, in MQL è un descrittore, non il punto - ma non è corretto creare una nuova copia dell'oggetto, questo funziona correttamente ora:

ma se seguite la vostra logica, allora questo codice creerà anche una copia dell'oggetto l nella funzione SetLabel() - ho passato un puntatore, non un riferimento?

No. Qui l è un parametro del metodo attraverso il quale passiamo il puntatore necessario. Qui va tutto bene. Il puntatore qui rimane sull'oggetto creato in precedenza. Qui non creiamo un nuovo oggetto e riassegniamo il puntatore ad esso con la perdita dell'oggetto precedente.
 
Artyom Trishkin:
No. Qui l è il parametro del metodo attraverso il quale passiamo il puntatore necessario. Qui è tutto a posto. Il puntatore qui rimane sull'oggetto creato in precedenza. Qui non creiamo un nuovo oggetto e riassegniamo il puntatore ad esso con la perdita dell'oggetto precedente.

non funziona ancora correttamente

questi "puntatori" in MQL sono fatti per lavorare nell'ambito della classe, non voglio creare una classe, dichiaro un puntatore globale e poi lo passo a qualsiasi funzione, e il fatto che creo un descrittore dell'oggetto in questa funzione non è la ragione per distruggere l'oggetto all'uscita dall'ambito locale della funzione

Sono un po' occupato in questo momento, ma ho bisogno di fare esempi di test senza grafica - penso che la stessa cosa accadrà se si entra nella funzione con un puntatore con valore POINTER_INVALID, si uscirà con lo stesso POINTER_INVALID , per riferimento, tutto funzionerà correttamente, ma penso che non si possa passare un puntatore con POINTER_INVALID per riferimento - ci sarà un errore nell'accesso al puntatore

 
Igor Makanu:

non funziona tutto correttamente comunque

questi "puntatori" in MQL sono fatti per lavorare nell'ambito della classe, non voglio creare una classe, mi basta forare e dichiarare un puntatore nell'ambito globale, poi passarlo a qualsiasi funzione e il fatto che creo un descrittore di oggetto in questa funzione non è la ragione per distruggere l'oggetto all'uscita dall'ambito locale della funzione

Penso che sarà lo stesso problema, se entrate con un valore POINTER_INVALID in questa funzione, uscirete con lo stesso valore POINTER_INVALID, per riferimento, tutto funzionerà correttamente, ma per riferimento non potete passare un puntatore con POINTER_INVALID - si verificherà un errore di accesso al puntatore.

Esattamente l'oggetto non viene distrutto. Dopo aver creato un nuovo oggetto all'interno del metodo, abbiamo già due oggetti. E c'è solo un puntatore - è stato passato al metodo come parametro formale. Così perdiamo il puntatore a uno degli oggetti.
 

Sono stato sorpreso di scoprire che era possibile dichiarare typedef con un puntatore a una funzione template.
Tuttavia, la felicità non durò a lungo.

template<typename T>
typedef bool (* callback)(T &);

template<typename T>
bool ff(T &){
   return true;
}

bool ff(int &){
   return true;
}


void OnStart(){
   int a;
   ff(a);
   
   callback<int> f_ptr_0 = ff;     //'<' - unexpected token     
   callback f_ptr_1 = ff;          //'ff' - function must have a body   
   callback f_ptr_2 = ff<int>;     //'ff<int>' - cannot resolve function address  //'ff<int>' - type mismatch   
}


Il typedef con un puntatore a una funzione template è una caratteristica prevista?

 
Un altro bug nel giardino dei typedef:
typedef void (* callback)(int &);

template<typename T>
void ff(T &){}


void OnStart(){
   int a = 0;
   //ff(a);                     //  если раскомментировать, то работает
   
   callback f_ptr = ff<int>;    //  'ff<int>' - function must have a body
   f_ptr(a);
}

Quando si lavora con i typedef, usare una funzione template con specializzazione esplicita non genera codice per quel template
Motivazione: