循环条件评估

Fak*_*ken 27 c++ optimization for-loop

只是一个简单的问题.

我有一个看起来像这样的循环:

for (int i = 0; i < dim * dim; i++)
Run Code Online (Sandbox Code Playgroud)

是否在每个循环中重新评估for循环中的条件?

如果是这样,做这样的事情会更有效吗?:

int dimSquare = dim * dim;
for (int i = 0; i < dimSquare; i++)
Run Code Online (Sandbox Code Playgroud)

谢谢

-Faken

bdo*_*lan 47

是的,在语义上它将在每个循环上进行评估.在某些情况下,编译器可能能够自动从循环中删除条件 - 但并非总是如此.特别是:

void foo(const struct rect *r) {
  for (int i = 0; i < r->width * r->height; i++) {
    quux();
  }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,编译器将无法移出乘法,因为它知道quux()修改的所有内容r.

一般来说,通常只有局部变量才有资格从循环中提取表达式(假设你从不拿地址!).虽然在某些条件下结构成员也可能符合条件,但是有很多事情可能导致编译器假设内存中的所有内容都已更改 - 例如,写入几乎任何指针或调用几乎任何函数.因此,如果您在那里使用任何非本地人,最好假设不会发生优化.

也就是说,一般来说,我只建议主动将潜在的昂贵代码移出条件,如果它:

  • 这样做不会影响可读性
  • 显然需要长时间(例如,网络访问)
  • 或者显示为分析的热点.

  • 请注意,在您的示例中,r可以是`const struct rect*`,并且不允许编译器*仍然*假设quux()不会通过别名以某种方式修改其数据成员.通常假设const激活所有编译器优化方式,但它并不像人们首先想到的那么简单. (7认同)
  • 是.'r'很可能指向一个全局变量.或全局变量指向的东西.等等. (3认同)

Luc*_*cas 37

通常,如果您要在循环中更改"dim"的值,则每次都会重新评估它.但是因为在你的例子中并非如此,一个体面的编译器会优化你的代码,你不会看到性能上的任何差异.

  • 但是不要忘记考虑使用局部变量进行循环控制的bdonlan建议 - 本地化使编译器更容易优化,因为它们的可见性有限(这也有助于读者理解,而不仅仅是编译器优化). (3认同)
  • 一个decenet编译器也希望将你的i ++变成++ i :-) (2认同)