Características del lenguaje mql5, sutilezas y técnicas - página 151

 
fxsaber:

La variable estática se inicializa en la primera llamada.

Es difícil adivinar por qué los desarrolladores lo hicieron, creo que es un error - la inicialización de una variable constante con un valor desconocido en tiempo de compilación

Así es como suelo comprobar qué y cuándo inicializarlo

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


En mi ejemplo, todo se inicializa correctamente y el compilador no permite asignar otro valor a la constante j - habrá un error de compilación

 
Vladimir Simakov:

El problema es que no vale la pena utilizarlo en ningún caso, porque es un error conceptual.

De todos modos, no vale la pena utilizarlo, porque es un error conceptual.

 
Alexey Navoykov:

De todos modos, no deberías usarlo, ya que es un error conceptual.

Pero, ¿por qué conceptual? Por el contrario, a veces no se sabe qué valor inicializar la variable estática en tiempo de compilación, la inicialización en la primera llamada ayuda.

 
Alexey Navoykov:

De todos modos, no vale la pena usarlo, ya que es un error conceptual.

Implementación de MVS C++17:

Variables locales estáticas

Las variables declaradas en el ámbito del bloque con el especificador static othread_local (desde C++11 ) tienen una duración de almacenamiento estáticao thread (desde C++11), pero se inicializan la primera vez que el control pasa por su declaración (a menos que su inicialización sea cero o constante, lo que puede realizarse antes de entrar en el bloque por primera vez). En todas las llamadas posteriores, se omite la declaración.

Si la inicialización lanza una excepción, la variable no se considera inicializada, y la inicialización se intentará de nuevo la próxima vez que el control pase por la declaración.

Si la inicialización entra recursivamente en el bloque en el que se está inicializando la variable, el comportamiento es indefinido.

Si varios hilos intentan inicializar la misma variable local estática de forma concurrente, la inicialización se produce exactamente una vez (se puede obtener un comportamiento similar para funciones arbitrarias con std::call_once).

Nota: las implementaciones habituales de esta función utilizan variantes del patrón de bloqueo de doble comprobación, que reduce la sobrecarga en tiempo de ejecución para las estáticas locales ya inicializadas a una única comparación booleana no atómica.

(desde C++11)

El destructor de una variable estática de ámbito de bloque se llama al salir del programa, pero sólo si la inicialización se realizó con éxito.

Los objetos estáticos locales de la función en todas las definiciones de la misma función en línea (que puede estar implícitamente en línea) se refieren al mismo objeto definido en una unidad de traducción.

Personalmente estoy a favor, si tal implementación es legal en mql, sólo hay que especificarlo en los documentos.

 
Vladimir Simakov:

Entonces, ¿por qué es conceptual? Por el contrario, a veces no se sabe con qué valor inicializar una variable estática en tiempo de compilación, es la inicialización en la primera llamada lo que ayuda.

Así que tenemos que inicializar con un valor cero (por defecto). ¿Y por qué inicializar con el primer valor encontrado? Entonces el comportamiento de la función está determinado por el orden de las llamadas de esta función, creando un efecto secundario. Y es incorrecto. Si quieres inicializar los internos desde fuera, es mejor que uses una clase, no una función.

Sin embargo, en realidad me equivoqué al decir que no puede compilar. En C++ funciona, curiosamente, aunque nunca se me ocurrió hacer tal cosa.

 
Alexey Navoykov: En C++ funciona, curiosamente, aunque nunca se me ocurrió hacerlo.

Allí siempre ha sido así, no hay problemas conceptuales, los problemas serían si fuera de otra manera

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

Y el orden de destrucción es estrictamente el contrario.

 
Vict:

Esto siempre ha sido así allí, no hay problemas conceptuales, habría problemas si fuera de otra manera

Su ejemplo es un poco diferente.
 
Slava:

Después de seleccionar el menú contextual "Editar", el navegador no encuentra el mq5 original en la misma ruta que el ex5.

Porque ex5 se ha movido a la carpeta de scripts desde Proyectos Compartidos, donde vive mq5

Lo arreglaré. Hagamos la misma búsqueda inteligente que en la configuración de los probadores

También existe una situación opuesta. En el Navegador de Favoritos, es imposible ir a mq5-edición (mq5 está disponible) si falta ex5 (hubo un error de compilación, por ejemplo). Por favor, arreglen esto también.

 
fxsaber:

También existe una situación inversa. En el Navegador de Favoritos, es imposible cambiar a la edición mq5 (mq5 está disponible) si falta ex5 (hubo un error de compilación, por ejemplo). Por favor, arreglen esto también.

2250 está bien.

Se ha precipitado. 2251 - no abre mq5.

 
fxsaber:

2250 está bien.

Apresuradamente. 2251 - no abre mq5.

¿Está ahí? ¿Lo tienes? ¿En qué camino se encuentra?

¿Cómo se puede reproducir?

Razón de la queja: