在循环后面声明变量还是在循环里面声明变量?

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

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

鉴于mql5编译器的所有优化,有什么区别吗?

 
pivalexander:

鉴于mql5编译器的所有优化,有什么区别吗?

在编译方面没有区别,所以请随意使用第二个选项。
 

就个人而言,我更喜欢前者。

以防万一。编译器可能很聪明,不会每次都分配内存,但在第一种情况下,我明确指定,但在第二种情况下,这是编译器隐含的结果,因为语言的逻辑是在一个块内创建一个变量,并在退出该块时将其删除。

而将int等同于字符串而不进行转换是不好的做法。

 
pivalexander:

鉴于mql5编译器的所有优化,有什么区别吗?

不要听信没有区别的说法。只使用第一个选项,是有区别的。不过我还没有研究过麦克尔公司的Disassm。

 
Georgiy Merts:

就个人而言,我更喜欢前者。

以防万一。编译器可能很聪明,不会每次都分配内存,但在第一种情况下,我明确指定,但在第二种情况下,这是编译器隐含的结果,因为语言的逻辑是在块内创建一个变量,在退出块时必须删除。

而将int等同于字符串而不进行转换是不好的做法。

乔治是对的,它不能保证。

我们得到了一个从 "数字 "到 "字符串 "的隐式转换的翘曲。


而这正是我们摆脱不确定性和扭曲的方法。

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

就个人而言,我更喜欢前者。

以防万一。编译器可能足够聪明,不会每次都分配内存,但在第一种情况下,我明确指定,但在第二种情况下,这是编译器工作的隐性结果

你在开玩笑吗? 对编译器来说,这是一个微不足道的情况,没有什么好谈的。 你可能对它如此偏执,以至于你只需要用汇编程序编码。 虽然现在连这都已经变得毫无意义了。 你必须努力去战胜现代编译器的优化。

p.s. 也许我对字符串缓冲器 的琐碎性有点激动。但在MQL中,不仅在循环内部,甚至在函数调用之间,它都能保证被保存。这个话题在这里不止一次讨论过
 

不要听他们的,他们会在这里告诉你很多东西的 ))

// c++
#include <iostream>
#include <string>
using namespace std;

void* operator new(size_t sz) {
    void *ptr = std::malloc(sz);
    if (ptr)
        return ptr;
    else
        throw std::bad_alloc{};
}


int main() {
        for (uint i = 0;  i < 3;  ++ i) {
                string s;
                char buf[10];
                sprintf(buf, "%u", i);
                s = "sfjhidfsrtea111";
                s += buf;
                cout << s << '\n';
        }
}

我编译了gcc -O3,在调试器下运行,在操作者new上设置断点,得到三个调用。与clang相同。

注意:如果字符串被从循环中取出,我就会得到一个调用。

 
Alexey Navoykov:

你在开玩笑吗? 对于编译器来说,这是一个微不足道的情况,没有什么好谈的。 如果你如此偏执,你可以纯粹用汇编程序写代码。 但即使是这样,如今也变得毫无意义了。 你必须努力去击败现代编译器的优化。

p.s. 也许我对字符串缓冲器 的琐碎性有点激动。但在MQL中,不仅在循环内部,甚至在函数调用之间,它都能保证被保存。这个话题在这里不止一次讨论过

不,我没有。

当然,在这种情况下,一个正常的编译器应该把循环内的变量声明带到外部。

我只是认为你应该永远相信编译器,相信自己。编译器的标准是,局部变量在声明时被创建,在声明它的块退出时被删除。因此,你应该首先关注这一原则,而不是等待编译器为你改进你的代码。

这不是效率的问题(现代编译器确实能给出非常高质量的代码),而是程序员的思维方案。 当我看Kodobase的源代码时,我经常想知道它们包含了多少简单的、但有潜在危险的小缺陷。在这种情况下,这还不是很关键,最多可能发生的是程序工作得慢一点。 真正的错误可能要棘手得多。

 
Vict:

不要听他们的,他们会在这里告诉你很多东西的 ))

我编译了gcc -O3,在调试器下运行,在操作者new上设置断点,得到三个调用。与clang相同。

因此,如果字符串被从循环中取出,我就会得到一个调用。

它不可能不这样做,因为你自己通过断点干扰了优化。 优化的本质是它不应该改变算法的逻辑。这就是为什么它不能被明确检测出来。 如果那里有一个断点,编译器当然无权把这段代码剪掉。 你期望编译器能跳过断点 吗?)

你只能通过编译代码或测量其性能来检测优化,所以这是你应该做的第一件事。冷静下来 )

 
等待测量)
 
Alexey Navoykov:

它不可能不这样做,因为你自己通过断点干扰了优化。 优化的要点是,它不能改变算法的逻辑。这就是为什么它不能被明确地检测出来。 如果那里有一个断点,编译器自然无权把这段代码剪掉。 你是否想到编译器可能会跳过断点?)

你只能通过编译代码或测量其性能来检测优化,所以这是你应该做的第一件事。冷静下来 )

伙计,这简直是疯狂的蠢事,有什么好评论的,完全是对调试器工作原理的误解。

关于速度--内存管理器不是那么愚蠢的,也不是会问操作系统的事实,可能会过度使用早期分配的。一般来说,怎么用就怎么用,由你自己决定。但你不应该让别人相信这一点,至少在你提供具体证据之前,他们在哪里?