Características da linguagem mql5, subtilezas e técnicas - página 151

 
fxsaber:

A variável estática é inicializada na primeira chamada.

É difícil adivinhar porque é que os criadores o fizeram, penso que é um bug - a inicialização de uma variável constante com um valor desconhecido em tempo de compilação

É assim que costumo verificar o quê e quando inicializá-lo

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


No meu exemplo, tudo inicializado correctamente e o compilador não permite atribuir mais valor à constante j - haverá um erro de compilação

 
Vladimir Simakov:

O problema é que não vale a pena utilizá-lo em qualquer caso, porque se trata de um erro conceptual.

Bem, não vale a pena utilizá-lo de qualquer forma, porque é um erro conceptual.

 
Alexey Navoykov:

Bem, não se deve usá-lo de qualquer maneira, pois é um erro conceptual.

Mas porquê conceptual? Pelo contrário, por vezes não se sabe que valor inicializar a variável estática em tempo de compilação, a inicialização à primeira chamada ajuda.

 
Alexey Navoykov:

Bem, não vale a pena usar de qualquer forma, pois trata-se de um erro conceptual.

Implementação de MVS C++17:

Variáveis estáticas locais

As variáveis declaradas no âmbito do bloco com o especificador estático outhread_local (desde C++11) têm duração de armazenamento estáticoou thread (desde C++11) mas são inicializadas na primeira vez que o controlo passa pela sua declaração (a menos que a sua inicialização seja zero ou inicialização constante, o que pode ser executado antes de o bloco ser inserido pela primeira vez). Em todas as outras chamadas, a declaração é ignorada.

Se a inicialização lançar uma excepção, a variável não é considerada como sendo inicializada, e a inicialização será tentada novamente na próxima vez que o controlo passar pela declaração.

Se a inicialização entrar recursivamente no bloco em que a variável está a ser inicializada, o comportamento é indefinido.

Se vários fios tentarem inicializar a mesma variável local estática ao mesmo tempo, a inicialização ocorre exactamente uma vez (comportamento semelhante pode ser obtido para funções arbitrárias com std::call_once).

Nota: as implementações habituais desta funcionalidade utilizam variantes do padrão de bloqueio duplamente verificado, o que reduz o tempo de execução para estáticas locais já inicializadas a uma única comparação booleana não atómica.

(desde C++11)

O destruidor de uma variável estática de âmbito de bloco é chamado na saída do programa, mas apenas se a inicialização tiver tido sucesso.

Os objectos estáticos locais em todas as definições da mesma função em linha (que podem estar implicitamente em linha) referem-se todos ao mesmo objecto definido numa única unidade de tradução.

Pessoalmente sou a favor, se tal implementação for legal em mql, basta especificá-la nos documentos.

 
Vladimir Simakov:

Então porque é conceptual? Pelo contrário, por vezes não se sabe com que valor inicializar uma variável estática no momento da compilação, é a inicialização de primeira chamada que ajuda.

Assim, precisamos de inicializar com um valor zero (por defeito). E porquê inicializar com o primeiro valor encontrado? Então o comportamento da função é determinado pela ordem das chamadas desta função, criando um efeito secundário. E é incorrecto. Se quiser inicializar os internos a partir do exterior, é melhor usar uma classe, não uma função.

No entanto, estava realmente errado ao dizer que não pode compilar. Em C++ funciona, por estranho que pareça, embora nunca me tenha ocorrido fazer tal coisa.

 
Alexey Navoykov: Em C++ funciona, por estranho que pareça, embora nunca me tenha ocorrido fazê-lo.

Sempre foi assim, sem problemas conceptuais, os problemas seriam se fosse de outra forma

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

E a ordem de destruição é estritamente o oposto.

 
Vict:

Este sempre foi o caso, não houve problemas conceptuais, haveria problemas se fosse de outra forma

O seu exemplo é um pouco diferente.
 
Slava:

Após seleccionar o menu de contexto "Editar", o navegador não consegue encontrar o mq5 original no mesmo caminho que o ex5.

Porque a ex5 foi movida para a pasta de scripts de Projectos Partilhados, onde vive a mq5

Vai resolvê-lo. Vamos fazer a mesma pesquisa inteligente que nas definições de teste

Há também uma situação oposta. Em Favorites Navigator, é impossível ir à edição de mq5 (mq5 está disponível) se faltar o ex5 (houve um erro de compilação, por exemplo). Por favor, conserte isto também.

 
fxsaber:

Há também uma situação inversa. Em Favorites Navigator, é impossível mudar para mq5-editing (mq5 está disponível) se faltar o ex5 (houve um erro de compilação, por exemplo). Por favor, conserte isto também.

2250 está bem.

Tem sido apressado. 2251 - não abre mq5.

 
fxsaber:

2250 está bem.

Apressadamente. 2251 - não abre mq5.

Está lá? Tem-lo? Em que caminho se encontra?

Como pode ser reproduzido?

Razão: