很多时候我看到的代码如下:
int s = a / x;
for (int i = 0; i < s; i++)
// do something
如果在for循环中,a
和x
都没有被修改,那么我可以简单地写一下:
for (int i = 0; i < a / x; i++)
// do something
然后假设编译器优化a/x
,即用常量替换它?
答案 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)
是的,你可以做到,但它不可读。