Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 回路条件评估_C++_Optimization_For Loop - Fatal编程技术网

C++ 回路条件评估

C++ 回路条件评估,c++,optimization,for-loop,C++,Optimization,For Loop,只是一个简单的问题 我有一个这样的循环: for (int i = 0; i < dim * dim; i++) for(int i=0;i

只是一个简单的问题

我有一个这样的循环:

for (int i = 0; i < dim * dim; i++)
for(int i=0;i
for循环中的条件是否在每个循环上都重新评估

如果是这样,这样做会更有效吗

int dimSquare = dim * dim;
for (int i = 0; i < dimSquare; i++)
int-dimSquare=dim*dim;
对于(int i=0;i
谢谢


-Faken

编译器将在循环开始之前预计算Dim*Dim的值

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

void foo(const struct rect *r) {
  for (int i = 0; i < r->width * r->height; i++) {
    quux();
  }
}
void foo(const struct rect*r){
对于(int i=0;iwidth*r->height;i++){
quux();
}
}
在这种情况下,编译器将无法将乘法移出,因为它知道
qux()
修改
r

通常,只有局部变量才有资格将表达式从循环中提升出来(假设您从未获取它们的地址!)。虽然在某些条件下,结构成员也可能符合条件,但有太多的情况可能会导致编译器假定内存中的所有内容都已更改—例如,写入几乎任何指针,或调用几乎任何函数。因此,如果您使用的是任何非局部变量,最好假设优化不会发生

也就是说,一般来说,我只建议在以下情况之一的情况下,主动将可能昂贵的代码移出该状态:

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

通常,例如,如果您要更改循环中“dim”的值,则每次都会重新评估该值。但是,因为在您的示例中不是这样,一个好的编译器会优化您的代码,并且您不会看到性能上的任何差异。

除非Dim可以在循环内修改。那么您的意思是,在for循环中,即使Dim的值在循环期间发生变化,循环也会运行,直到达到预编译的值为止?或者当dim在循环的中途发生变化时,程序会重新计算它吗?@Faken,如果dim有任何变化的可能性,编译器会在每个循环中重新计算它。但是在这个例子中,当问题被问到时,它不能。因此,它将在循环之前预计算一次。请注意,在您的示例中,r可能是
const struct rect*
,并且编译器仍然不允许假定quux()没有通过别名以某种方式修改其数据成员。通常认为const会激活各种编译器优化,但它并不像人们想象的那么简单。@onebyone:的确如此。然而,限制可能会对这里有所帮助。对于C++编译器,也就是C99编译器,因此支持限制。严格的别名规则有助于“写入几乎任何指针”,但不能“调用几乎任何函数”。内联应该对函数有帮助。是的。”r'很可能指向一个全局变量。或者全局变量指向的对象。或具有非全局名称的“全局”,例如静态类成员。或者甚至是一个函数静态变量。很抱歉,对于那些想了很久的答案的人,但这个答案以一种清晰简洁的方式向我解释了一切。但别忘了牢记bdonlan关于使用局部变量进行循环控制的建议——局部变量使编译器更容易优化,因为它们的可见性有限(这也有助于读者理解,而不仅仅是编译器优化).如果我是你,我不会道歉。这让bdonlan在“民粹主义”徽章上有了一个不错的机会,获得了9张选票(在撰写本文时),如果Lulu一个接一个地获得8:-)@那么,如果你这样说的话,我想我也必须投票支持这个;)Deceet编译器也有望将您的i++转换为++i:-)