4

在编写一个for开始和结束条件都知道的循环时,哪种方式更好?假设我必须迭代一个循环以添加大小为 5 的数组元素。在这种情况下,就执行时间而言,以下哪一项会更有效?哪一个会提供更好的性能?

for (i = 0; i < 5; i++)
{
    /* logic */
}

或者

for (i = 4; i >= 0; i--)
{
    /* logic */
}

除了写作难i = 5 - 1;i = 4;还有其他考虑吗?

4

7 回答 7

9

通常建议集中精力使代码尽可能清晰和合乎逻辑,而不用担心微优化或其他因素。在您的情况下,第一个是更好的选择,因为大多数程序员更习惯于按该顺序遍历数组。

两个版本将具有相同的结果(假设它们已正确实现)并且将具有完全相同的运行时间。

编辑:@Zane 在评论中提到,前段时间向后循环到零更快。之所以如此,是因为将变量与零进行比较更快。鉴于当时计算机的速度要慢得多,因此鼓励进行此类优化。那些日子真的结束了……

于 2012-11-08T10:48:50.280 回答
4

你的代码有问题。第一个循环很好,但第二个 while 永远不会执行:它运行了 0 次。它应该是

for(i=4;i>=0;i--){}

此外,如果您问哪个更好,这是您的选择,您喜欢哪个。对我来说,我觉得第一个更舒服。

于 2012-11-08T10:49:57.307 回答
2

在大多数情况下,这无关紧要,但是在某些情况下,不明显的副作用可能会干扰。考虑一个循环:

for(int i = 0; i < strlen(str); i++) {/* do stuff on i-th elem */}. 在每次迭代中,都会重新评估 strlen(str)(除非经过编译器优化),即使它完全没有必要;程序员很可能甚至没有考虑到这一点。可能值得将循环替换为:

for(int i = strlen(str); i > 0; i--) {/* do stuff on i-th elem */}. 这里字符串的长度只会被评估一次。

当然,在第一个循环中,也可以通过使用附加变量来保存字符串的长度来避免该问题,但这只是不必要的噪音,与程序逻辑无关。

于 2012-11-08T10:57:37.293 回答
2

最明显的答案是:哪一个有你想要的语义?他们以不同的顺序访问对象。

作为一般规则,如果没有其他考虑,人们期望升序,这就是您在访问对象时应该使用的。在 C++ 中,为此使用迭代器更为惯用。普通迭代器按升序访问,反向迭代器按降序访问。如果您不明确需要降序,则应使用普通迭代器。这是人们所期望的,当你使用反向迭代器时,读者首先会问为什么。此外,我还没有测量,但如果普通迭代器比反向迭代器更快,我不会感到惊讶。在 Java 中,迭代器也是惯用的,并且没有反向迭代器。

如果我在访问时确实需要降序,我将使用 while 循环(如果我没有反向迭代器,它会为我做);我发现类似:

int index = numberOfElements;
while ( index != 0 ) {
    -- index;
    //  ...
}

比任何替代方案都更具可读性(并且更容易正确)。

如果您不访问对象,而只是计数,那么降序对我来说似乎更自然:控制变量包含剩余的次数。而且由于计数从不用作索引,因此将它作为索引是一次性的这一事实没有问题,您可以使用传统的for.

for ( int count = numberOfTimes; count != 0; -- count ) {
    //  ...
}

但这确实是风格问题。我也看到了很多上升循环。

于 2012-11-08T11:16:31.100 回答
0

我相信大多数程序员可以使用第一种方法(i++)更快地理解你的代码。除非您需要反向处理数组,否则我会坚持使用您的第一种方法。至于性能,我相信这两种解决方案都没有什么好处。

此外,您可能需要考虑使用 for..each (增强的 for)语法,该语法相当整洁。

    int[] x = {1,2,3,4,5};

    for(int y: x){
        System.out.println(y);
    }
于 2012-11-08T10:48:01.413 回答
0

我想说 i++ 的循环更容易理解。此外,后退可能会使处理器缓存的使用欠佳,但通常编译器/虚拟机比这更智能。

于 2012-11-08T10:50:54.210 回答
0

增量 for 循环或减量 for 循环是根据您希望使用 counter 变量的方式或它的外观来选择的

  • 如果您按升序访问某个数组,则将使用递减的 for 循环

    for (i = 0; i < 5; i++) { arr[i]; }

  • 如果您按降序访问某个数组或列表,则使用增量 for 循环

    for (i = 5; i > 0 ; i--) { arr[i-1]; }

  • 如果计数器编号对访问的值没有意义,则查看代码的可读性。并且增量 for 循环看起来更令人赏心悦目。

于 2012-11-08T11:17:39.237 回答