Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 151

 
fxsaber:

La variabile statica viene inizializzata alla prima chiamata.

È difficile indovinare perché gli sviluppatori l'abbiano fatto, penso che sia un bug - l'inizializzazione di una variabile costante con un valore sconosciuto al momento della compilazione

È così che di solito controllo cosa e quando inizializzarlo

//+------------------------------------------------------------------+
void OnStart()
{
   f(333);
   f(2);
}
//+------------------------------------------------------------------+
int init_static()
{
   Print(__FUNCTION__);
   return(1);
}

void f( const int i )
{
  static const int j = init_static();
  
  Print(__FUNCTION__," , j =",j);
}

2019.11.30 11:09:32.456 tst (EURUSD,H1) init_static

2019.11.30 11:09:32.457 tst (EURUSD,H1) f , j =1

2019.11.30 11:09:32.457 tst (EURUSD,H1) f , j =1


Nel mio esempio, tutto inizializzato correttamente e il compilatore non permette di assegnare un ulteriore valore alla costante j - ci sarà un errore di compilazione

 
Vladimir Simakov:

Il problema è che non vale la pena usarlo in ogni caso, perché è un errore concettuale.

Beh, non vale la pena usarlo comunque, perché è un errore concettuale.

 
Alexey Navoykov:

Beh, non dovreste usarlo comunque, perché è un errore concettuale.

Ma perché concettuale? Al contrario, a volte non si sa che valore inizializzare la variabile statica in fase di compilazione, l'inizializzazione alla prima chiamata aiuta.

 
Alexey Navoykov:

Beh, non usatelo comunque, perché è un errore concettuale.

Implementazione di MVS C++17:

Variabili locali statiche

Le variabili dichiarate nell'ambito del blocco con lo specificatore staticorthread_local (dal C++11) hanno una durata di memorizzazione staticao thread (dal C++11) ma sono inizializzate la prima volta che il controllo passa attraverso la loro dichiarazione (a meno che la loro inizializzazione sia zero o costante, che può essere eseguita prima che il blocco sia entrato per la prima volta). In tutte le chiamate successive, la dichiarazione viene saltata.

Se l'inizializzazione lancia un'eccezione, la variabile non è considerata inizializzata, e l'inizializzazione sarà tentata di nuovo la prossima volta che il controllo passa attraverso la dichiarazione.

Se l'inizializzazione entra ricorsivamente nel blocco in cui la variabile viene inizializzata, il comportamento è indefinito.

Se più thread tentano di inizializzare la stessa variabile locale statica simultaneamente, l'inizializzazione avviene esattamente una volta (un comportamento simile può essere ottenuto per funzioni arbitrarie con std::call_once).

Nota: le implementazioni usuali di questa caratteristica usano varianti del modello di chiusura a doppio controllo, che riduce l'overhead di runtime per le statiche locali già inizializzate ad un singolo confronto booleano non atomico.

(da C++11)

Il distruttore di una variabile statica block-scope viene chiamato all'uscita del programma, ma solo se l'inizializzazione è avvenuta con successo.

Gli oggetti statici locali alle funzioni in tutte le definizioni della stessa funzione inline (che può essere implicitamente inline) si riferiscono tutti allo stesso oggetto definito in un'unità di traduzione.

Personalmente sono d'accordo, se una tale implementazione è legale in mql, basta specificarlo nei documenti.

 
Vladimir Simakov:

Allora perché è concettuale? Al contrario, a volte non si sa con quale valore inizializzare una variabile statica in fase di compilazione, è l'inizializzazione della prima chiamata che aiuta.

Quindi dobbiamo inizializzare con un valore zero (predefinito). E perché inizializzare con il primo valore incontrato? Poi il comportamento della funzione è determinato dall'ordine delle chiamate di questa funzione, creando un effetto collaterale. E non è corretto. Se volete inizializzare gli interni dall'esterno, è meglio usare una classe, non una funzione.

Comunque, in realtà mi sono sbagliato nel dire che non può compilare. In C++ funziona, stranamente, anche se non mi è mai venuto in mente di fare una cosa del genere.

 
Alexey Navoykov: In C++ funziona, stranamente, anche se non mi è mai venuto in mente di farlo.

È sempre stato così lì, nessun problema concettuale, i problemi sarebbero se fosse altrimenti

void fn() {
   static int i = fn_from_other_cpp();
}

E l'ordine di distruzione è strettamente opposto.

 
Vict:

Questo è sempre stato il caso lì, nessun problema concettuale, ci sarebbero problemi se fosse altrimenti

Il tuo esempio è un po' diverso.
 
Slava:

Dopo aver selezionato il menu contestuale "Modifica", il navigatore non trova l'originale mq5 nello stesso percorso di ex5.

Perché ex5 è stato spostato nella cartella scripts da Shared Projects, dove vive mq5

Lo sistemerà. Facciamo la stessa ricerca intelligente delle impostazioni del tester

C'è anche una situazione opposta. In Favorites Navigator, è impossibile passare a mq5-editing (mq5 è disponibile) se manca ex5 (c'è stato un errore di compilazione, per esempio). Per favore, sistemate anche questo.

 
fxsaber:

C'è anche una situazione inversa. In Favorites Navigator, è impossibile passare a mq5-editing (mq5 è disponibile) se manca ex5 (c'è stato un errore di compilazione, per esempio). Per favore, sistemate anche questo.

2250 va bene.

È stato affrettato. 2251 - non apre mq5.

 
fxsaber:

2250 va bene.

In fretta. 2251 - non apre mq5.

È lì? Ce l'hai? Su quale sentiero si trova?

Come si può riprodurre?

Motivazione: