`for(...)`语句中的计算

时间:2015-03-25 18:12:17

标签: c++

很多时候我看到的代码如下:

int s = a / x;
for (int i = 0; i < s; i++)
    // do something

如果在for循环中,ax都没有被修改,那么我可以简单地写一下:

for (int i = 0; i < a / x; i++)
    // do something

然后假设编译器优化a/x,即用常量替换它?

5 个答案:

答案 0 :(得分:8)

int s = a / x最重要的部分是变量名称。它给出了你的语法语义,让你记住12个月之后你为什么要把一件事分成另一件事。您无法在for语句中为表达式命名,因此您将失去自我记录的性质。

const auto monthlyAmount = (int)yearlyAmount / numberOfMonths;
for (auto i = 0; i < monthlyAmount; ++i)
    // do something

通过这种方式,提取变量不是编译器优化,它是人类可维护性优化。

答案 1 :(得分:3)

如果编译器可以确保for循环中间的表达式中使用的变量在迭代之间不会改变,它可以优化计算,在循环开始时执行一次,而不是每次迭代。

但是,请考虑使用的变量是全局变量,或对函数外部变量的引用,并在for循环中调用函数。该函数可以更改这些变量。如果编译器能够在那时看到足够的代码,它可以找出决定是否优化的情况。但是,编译器只愿意看到目前为止(否则编译需要更长的时间),所以通常你不能假设优化已经完成。

答案 2 :(得分:0)

对优化的关注可能源于在每次迭代之前评估条件的事实。如果这是一项潜在的昂贵操作,而且您不需要反复进行操作,则可以将其从循环中提取出来:

const std::size_t size = s.size(); // just an example
for (std::size_t i = 0; i < size; ++i)
{
}

对于廉价的操作,这可能是一个过早的优化,编译器可能会生成相同的代码。唯一可以确定的方法是检查生成的汇编代码。

答案 3 :(得分:0)

这些问题的问题在于它们不能一概而论。编译器将执行哪些优化,哪些不能仅通过案例分析来确定。 如果下列其中一个成立,我当然希望编译器能够这样做:

1)A和B都是局部变量,其地址永远不会被采用。

2)循环中的代码完全内联。

在实践中,最后一个要求并不像看起来那么难,因为如果身体中的函数无法内联,那么它们的运行时间可能会使重新计算边界的时间相形见绌

答案 4 :(得分:-3)

是的,你可以做到,但它不可读。