Declarando variáveis atrás do laço ou dentro do laço? - página 2

 
Georgiy Merts:

Não, não estou.

Certamente, um compilador normal neste caso deve trazer uma declaração variável dentro de um laço para o exterior.

Eu só acho que você deve sempre confiar no compilador e confiar em si mesmo. É um padrão de compilação que uma variável local é criada quando é declarada e é removida quando o bloco em que foi declarada é abandonado. Portanto, você deve se concentrar neste princípio em primeiro lugar e não esperar que o compilador melhore seu código para você.

Então eu digo que se você quer "melhorar", vá para assembler, se você precisa controlar tudo você mesmo... Afinal de contas, o caso que você acabou de descrever não é nada. Há coisas muito mais complicadas. O OOP é definitivamente contra-indicado para você. Você não saberá se o compilador degenerou ou não um determinado método virtual em uma chamada regular ou aparou uma verificação de ponteiro desnecessária... O que você pode fazer em um MQL gerenciado com tal paranóia? )

E ajustar o código para se adequar às peculiaridades do compilador (e imaginárias, por exemplo), em detrimento da correção e confiabilidade do código, obviamente não é o que um bom programador deve fazer. E aqui estamos falando exatamente sobre a incorreção do código. A variável deve ser declarada diretamente no bloco em que é utilizada.

 
Vict:

Cara, isso é simplesmente uma bobagem, o que há para comentar, uma completa falta de compreensão de como funciona o depurador.

Você tem.
 
Alexey Navoykov:
Você tem.

Como no jardim de infância )))) Explico para aqueles que estão no tanque: primeiro compilamos g++ 1.cpp, não há pontos de parada lá, o compilador não sabe nada sobre eles. Em seguida, executar debugger: gdb a.out, e só agora colocar breakpoint.

Você entendeu o absurdo que disse?

 
Alexey Navoykov:

Você pode detectar a otimização somente compilando o código ou medindo seu desempenho. Essa é a primeira coisa que você deve fazer. E acalme-se )

2019.08.18 10:28:12.826 SpeedTest (EURUSD,H1) 1. s1=rand(): loops=100000000 ms=7031

2019.08.18 10:28:19.885 SpeedTest (EURUSD,H1) 2. s2=rand(): loops=100000000 ms=7063

2019.08.18 10:28:27.037 SpeedTest (EURUSD,H1) 3. s3=rand(): loops=100000000 ms=7140

2019.08.18 10:28:34.045 SpeedTest (EURUSD,H1) 4. s4=rand(): loops=100000000 ms=7016

2019.08.18 10:28:41.135 SpeedTest (EURUSD,H1) 5. s5=rand(): loops=100000000 ms=7094

2019.08.18 10:28:47.896 SpeedTest (EURUSD,H1) 1. q=rand(): loops=100000000 ms=6750

2019.08.18 10:28:54.659 SpeedTest (EURUSD,H1) 2. q=rand(): loops=100000000 ms=6765

2019.08.18 10:29:01.447 SpeedTest (EURUSD,H1) 3. q=rand(): loops=100000000 ms=6797

2019.08.18 10:29:08.257 SpeedTest (EURUSD,H1) 4. q=rand(): loops=100000000 ms=6797

2019.08.18 10:29:15.102 SpeedTest (EURUSD,H1) 5. q=rand(): loops=100000000 ms=6844

//+------------------------------------------------------------------+
//|                                                    SpeedTest.mq5 |
//|                                                            IgorM |
//|                              https://www.mql5.com/ru/users/igorm |
//+------------------------------------------------------------------+
#property copyright "IgorM"
#property link      "https://www.mql5.com/ru/users/igorm"
#property version   "1.00"
#define  N 8

#define    test(M,S,EX) {uint mss=GetTickCount();ulong nn=(ulong)pow(10,M);for(ulong tst=0;tst<nn&&!_StopFlag;tst++){EX;} \
                        printf("%s: loops=%i ms=%u",S,nn,GetTickCount()-mss);}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   string s1; srand(GetTickCount()); test(N,"1. s1=rand()",s1=IntegerToString(rand()));
   string s2; srand(GetTickCount()); test(N,"2. s2=rand()",s2=IntegerToString(rand()));
   string s3; srand(GetTickCount()); test(N,"3. s3=rand()",s3=IntegerToString(rand()));
   string s4; srand(GetTickCount()); test(N,"4. s4=rand()",s4=IntegerToString(rand()));
   string s5; srand(GetTickCount()); test(N,"5. s5=rand()",s5=IntegerToString(rand()));

   srand(GetTickCount()); test(N,"1. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"2. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"3. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"4. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"5. q=rand()",string q=IntegerToString(rand()));
  }
//+------------------------------------------------------------------+
 
Eu cavei sob o depurador para código similar, mas sem operador de usuário novo, bem, poderia haver algumas dúvidas - o operador de usuário não está otimizado. Apanhei uma chamada de malloc() da libc. O resultado: string in loop - uma chamada antes de cada impressão, fora do loop - uma chamada antes de um lote de impressões. Não pode haver dúvidas sobre isso, apenas a primeira variante é melhor. Claro, é possível que algo seja diferente em µl, mas é melhor ser guiado por idiomas maduros.
 
#define  N 9

2019.08.18 10:37:59.620 SpeedTest (EURUSD,H1) 1. s1=rand(): loops=1000000000 ms=70672

2019.08.18 10:39:10.352 SpeedTest (EURUSD,H1) 2. s2=rand(): loops=1000000000 ms=70719

2019.08.18 10:40:21.908 SpeedTest (EURUSD,H1) 3. s3=rand(): loops=1000000000 ms=71562

2019.08.18 10:41:32.315 SpeedTest (EURUSD,H1) 4. s4=rand(): loops=1000000000 ms=70407

2019.08.18 10:42:42.996 SpeedTest (EURUSD,H1) 5. s5=rand(): loops=1000000000 ms=70687

2019.08.18 10:43:50.964 SpeedTest (EURUSD,H1) 1. q=rand(): loops=1000000000 ms=67969

2019.08.18 10:44:58.887 SpeedTest (EURUSD,H1) 2. q=rand(): loops=1000000000 ms=67922

2019.08.18 10:46:06.829 SpeedTest (EURUSD,H1) 3. q=rand(): loops=1000000000 ms=67937

2019.08.18 10:47:14.602 SpeedTest (EURUSD,H1) 4. q=rand(): loops=1000000000 ms=67766

2019.08.18 10:48:22.428 SpeedTest (EURUSD,H1) 5. q=rand(): loops=1000000000 ms=67828

 

Igor Makanu:

#define    test(M,S,EX) {uint mss=GetTickCount();ulong nn=(ulong)pow(10,M);for(ulong tst=0;tst<nn&&!_StopFlag;tst++){EX;} \

Cara, a "barra de espaço" não está funcionando para você? Não é a primeira vez que reparo nisso. Ou você está economizando bytes em seu disco rígido? )

 
Alexey Navoykov:

Você está brincando? É uma situação tão trivial para um compilador que não há nada para se falar. Mas você não pode ser tão paranóico sobre isso. ) Embora até isso esteja se tornando insensato hoje em dia. Você terá que se esforçar muito para vencer a otimização dos compiladores modernos.

p.s. Talvez eu estivesse um pouco excitado com a trivialidade no caso do buffer de cordas. Mas é garantido ser salvo em MQL, não apenas dentro do laço, mas até mesmo entre chamadas de função. Este tópico foi discutido aqui mais de uma vez

Tenho uma suspeita de que o autor desta declaração não sabe de todo como funciona o processador, a memória e o compilador... Aposto que qualquer um de seus códigos pode ser acelerado pelo menos dez vezes, ou mesmo centenas de vezes. Por causa de tais codificadores de merda, a maioria dos produtos é agora insuportavelmente lenta nos computadores mais potentes com dezenas de núcleos, enquanto você só precisa pensar um pouco... Mas algumas pessoas pensam: "Por que pensar? Você tem que codificar..."

Para sua informação, nenhum compilador no momento aprendeu a entender o que o programador queria obter como resultado. Ele pode desenrolar alguns loops e otimizar alguns acessos à memória para manter os dados em cache do processador, mas se o código não foi otimizado para começar e é escrito em um só lugar, nenhum compilador pode ajudá-lo...

P.S. Leia a seu gosto um livro divertido de Chris Kaspersky"Program Optimization Technique". Uso Eficiente da Memória".

 
Alexey Volchanskiy:

Georges está certo, não é garantido.

E obtemos uma conversão implícita de 'número' para 'cordel'.


E é exatamente assim que você se livra da ambigüidade e das deformações.

for (int i = 0; i < 1000; i++)
   {
      static string st = IntegerToString(i);
      ...
   }

Foi sempre assim que o fiz.

string st = (string)i;

E qual é o objetivo da estática? A tarefa só funcionará uma vez na primeira iteração.


Decidi medir a velocidade de execução.

   CStopWatch sw; // Секундомер, для замера времени
   
   sw.Start();
   for (int i = 0; i < 10000000; i++)
   {
      string st = (string)i;
   }
   pr("Test1, время выполнения: " + sw.Stop());

   sw.Start();
   string st = "";
   for (int i = 0; i < 10000000; i++)
   {
      st = (string)i;
   }
   pr("Test2, Время выполнения: " + sw.Stop());

O resultado:

Test1, время выполнения: 0.548275 сек.
Test2, Время выполнения: 0.313978 сек.

O resultado é estável, o código com a declaração de uma variável após o loop, funciona mais rapidamente

 
Alexey Navoykov:

Cara, a "barra de espaço" não está funcionando para você? Não é a primeira vez que reparo nisso. Ou você está economizando bytes em seu disco rígido? )

Não, este código não é meu, eu o aperfeiçoei um pouco - copiei o código para mim mesmo do tópico sobre "busca de ponto e vírgula" e o usei para perguntas controversas, sou preguiçoso demais para mudá-lo,

Eu tenho espaços e sou preguiçoso demais para fazê-lo ))))

ZS: me dê um código modelo, eu o copiarei para mim mesmo, será como você quiser no futuro, estou em princípio, isso não me incomoda

ZS: aqui AD :

#define    test(M,S,EX) {                                 \
uint mss=GetTickCount();                                 \
ulong nn=(ulong)pow(10,M);                               \
for(ulong tst=0;tst<nn && !_StopFlag;tst++) \
{ EX; }                                                  \
printf("%s: loops=%i ms=%u",S,nn,GetTickCount()-mss);}