Caractéristiques du langage mql5, subtilités et techniques - page 151

 
fxsaber:

La variable statique est initialisée lors du premier appel.

Il est difficile de deviner pourquoi les développeurs ont fait cela, je pense qu'il s'agit d'un bug - l'initialisation d'une variable constante avec une valeur inconnue au moment de la compilation.

C'est comme ça que je vérifie habituellement ce qu'il faut initialiser et quand le faire.

//+------------------------------------------------------------------+
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


Dans mon exemple, tout a été initialisé correctement et le compilateur ne permet pas d'attribuer une autre valeur à la constante j - il y aura une erreur de compilation.

 
Vladimir Simakov:

Le problème est que cela ne vaut pas la peine de l'utiliser dans tous les cas, car il s'agit d'une erreur conceptuelle.

De toute façon, ce n'est pas la peine de l'utiliser, car il s'agit d'une erreur conceptuelle.

 
Alexey Navoykov:

De toute façon, vous ne devriez pas l'utiliser, car il s'agit d'une erreur conceptuelle.

Mais pourquoi conceptuel ? Au contraire, parfois vous ne savez pas quelle valeur donner à une variable statique au moment de la compilation, l'initialisation au premier appel est utile.

 
Alexey Navoykov:

De toute façon, ne l'utilisez pas, car c'est une erreur conceptuelle.

Mise en œuvre de MVS C++17 :

Variables locales statiques

Les variables déclarées à la portée du bloc avec le spécificateur staticouthread_local (depuis C++11) ont une durée de stockage statiqueou thread (depuis C++11) mais sont initialisées la première fois que le contrôle passe par leur déclaration (à moins que leur initialisation ne soit nulle ou constante, ce qui peut être effectué avant la première entrée dans le bloc). Lors de tous les autres appels, la déclaration est ignorée.

Si l'initialisation lève une exception, la variable n'est pas considérée comme initialisée, et l'initialisation sera à nouveau tentée la prochaine fois que le contrôle passera par la déclaration.

Si l'initialisation entre récursivement dans le bloc dans lequel la variable est initialisée, le comportement est indéfini.

Si plusieurs threads tentent d'initialiser la même variable locale statique simultanément, l'initialisation se produit exactement une fois (un comportement similaire peut être obtenu pour des fonctions arbitraires avec std::call_once).

Remarque : les implémentations habituelles de cette fonctionnalité utilisent des variantes du modèle de verrouillage à double vérification, qui réduit la surcharge d'exécution pour les statiques locales déjà initialisées à une seule comparaison booléenne non atomique.

(depuis C++11)

Le destructeur d'une variable statique de type bloc est appelé à la sortie du programme, mais seulement si l'initialisation s'est déroulée correctement.

Les objets statiques locaux à une fonction dans toutes les définitions de la même fonction en ligne (qui peut être implicitement en ligne) font tous référence au même objet défini dans une unité de traduction.

Personnellement, je suis tout à fait pour, si une telle implémentation est légale dans mql, il suffit de le préciser dans la docs.

 
Vladimir Simakov:

Alors pourquoi est-ce conceptuel ? Au contraire, parfois on ne sait pas avec quelle valeur initialiser une variable statique au moment de la compilation, c'est l'initialisation au premier appel qui aide.

Nous devons donc initialiser avec une valeur nulle (par défaut). Et pourquoi initialiser avec la première valeur rencontrée ? Le comportement de la fonction est alors déterminé par l'ordre des appels de cette fonction, ce qui crée un effet secondaire. Et c'est incorrect. Si vous voulez initialiser des internes depuis l'extérieur, vous feriez mieux d'utiliser une classe, pas une fonction.

En fait, j'avais tort de dire qu'il ne pouvait pas compiler. En C++, il fonctionne, assez curieusement, bien que je n'aie jamais eu l'idée de faire une telle chose.

 
Alexey Navoykov: En C++, cela fonctionne, assez curieusement, bien que cela ne m'ait jamais effleuré.

Ça a toujours été comme ça là-bas, aucun problème conceptuel, les problèmes seraient s'il en était autrement.

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

Et l'ordre de destruction est strictement opposé.

 
Vict:

Cela a toujours été le cas là-bas, aucun problème conceptuel, il y aurait des problèmes s'il en était autrement...

Votre exemple est un peu différent.
 
Slava:

Après avoir sélectionné le menu contextuel "Edit", le navigateur ne trouve pas l'original mq5 dans le même chemin que ex5.

Parce que ex5 a été déplacé vers le dossier scripts à partir de Shared Projects, où se trouve mq5.

Je vais le réparer. Faisons la même recherche intelligente que dans les paramètres du testeur

Il existe également une situation inverse. Dans le Navigateur des Favoris, il est impossible d'accéder à mq5-editing (mq5 est disponible) si ex5 est absent (il y a eu une erreur de compilation, par exemple). Veuillez réparer cela aussi.

 
fxsaber:

Il existe également une situation inverse. Dans le Navigateur des Favoris, il est impossible de passer à l'édition mq5 (mq5 est disponible) si ex5 est absent (il y a eu une erreur de compilation, par exemple). Veuillez réparer cela aussi.

2250 c'est bien.

Cela a été précipité. 2251 - n'ouvre pas mq5.

 
fxsaber:

2250 c'est bien.

En toute hâte. 2251 - n'ouvre pas mq5.

Il est là ? Vous l'avez ? Sur quel chemin se trouve-t-il ?

Comment peut-on le reproduire ?

Raison: