循环的编译器优化

时间:2014-06-02 07:04:39

标签: c++ c optimization compiler-construction

我经常注意到以下模式:

for (int i = 0; i < strlen(str); ++i) {
  // do some operations on string
}

上述循环的复杂性为O(N²),因为strlen的复杂性为N,并且每次迭代都会进行比较。

但是,如果我们在循环之前计算strlen并使用该常量,则循环的复杂性将减少到O(N)

我相信还有很多其他优化措施。

编译器是否进行了这样的优化,或者程序员是否必须采取预防措施来防止它?

4 个答案:

答案 0 :(得分:1)

虽然我没有任何确凿的证据,但我的猜测是:

编译器对变量str进行数据流分析。如果它可能在循环内被修改或标记为volatile,则无法保证strlen(str)在迭代之间保持不变,因此无法缓存。否则,缓存应该是安全的,并且会进行优化。

答案 1 :(得分:1)

是的,好的优化器能够做到这种转换,如果他们可以确定字符串在循环体中保持不变。它们可以拉出保持不变的循环表达式。

无论如何,如果您将所有字符都转换为大写字母,编译器很难推断字符串长度不会发生变化。

我个人赞成&#34;防守&#34;方法,不依赖于高级编译技能,并自己做明显的优化。如果代码将被移植到不同的环境,使用较差的编译器,或者只是怀疑。

还要考虑优化已关闭的情况。

答案 2 :(得分:0)

了解编译器做什么,可以做什么,不能做什么的第一步是将您的意图写入代码并看看会发生什么:

const int len = strlen(str);
for (int i=0; i<len; ++I)
{
  // do some operations which DO NOT CHANGE the length of str
}

当然,你有责任不改变循环中str的长度......你可以小写,大写,交换或替换字符......你可能会断言()&#39;如果你真的关心(在调试版本中)。在这种情况下,您将您的意图传达给编译器,如果您很幸运并且使用了一个好的编译器,那么您可能会得到您想要的东西。

我真的怀疑这种优化会对你的代码产生任何影响:如果你正在进行繁重的字符串操作,你会(1)知道你是使用长字符串还是短字符串,(2)使用一个库( a)明确跟踪字符串的长度,(b)使(特别是重复的)字符串连接更便宜,因为它在C中。

答案 3 :(得分:0)

尝试

 for (int i = 0; str[i]; ++i) {
   // do some operations on string 
 }

由于strlen基本上是这样做的

相关问题