我应该如何摆脱循环?

Mat*_*ath 2 c c++ performance break

每当我需要从for(unsigned int i=0;i<bound;++i)C++中的表达式中突破时,我只需设置索引变量i=bound,方法与本答案中描述的相同.我倾向于避免这种break说法,因为老实说,我对它实际上做的事情并不了解.

比较两个说明:

for(unsigned int i=0;i<bound;++i) {
    if (I need a break) {
    break;
    }
}
Run Code Online (Sandbox Code Playgroud)

for(unsigned int i=0;i<bound;++i) {
    if (I need a break) {
    i=bound;
    }
}
Run Code Online (Sandbox Code Playgroud)

我推测第二种方法做一个额外的变量集,然后在i和之间进行一次额外的比较,从性能的角度来看bound,它看起来更昂贵.问题是,打电话break,然后进行这两项测试会更便宜吗?编译的二进制文件是否有所不同?是否存在第二种方法中断的实例,或者我可以安全地选择这两种方法中的任何一种?


相关:`break`是否只适用于`for`,`while`,`do-while`,`switch'和`if`语句?

在没有break语句的情况下突破循环[C]

Jey*_*ram 6

使用break将是更具前瞻性和更合乎逻辑的.

考虑以下示例,

for (i = 0; i < NUM_OF_ELEMENTS; i++)
{
     if(data[i] == expected_item)
         break;
} 

printf("\n Element %d is at index %d\n", expected_item, i);
Run Code Online (Sandbox Code Playgroud)

但是第二种方法在这里没有用.

  • 在这一点上考虑性能是不成熟的优化.你应该做更清楚的事情,那就是使用`break`. (7认同)

Mat*_*lia 5

我想到了三个主要的技术差异:

  • 正如其他人所说,如果您的索引变量不限于for范围break,则它保持不变,而您的方法会破坏其内容;当您搜索时,例如使用break代码的数组更简洁(您不必保留额外的变量来记下您停止的位置);
  • break立即退出循环;您的方法要求您执行身体的其余部分。当然,你总是可以写:

    for(int i=0; i<n; ++i) {
        if(...) {
            i=n;
        } else {
            rest of the loop body
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    但它给你的循环增加了视觉和逻辑上的混乱;

  • break几乎肯定会被翻译成一个简单jmp的指令,就在循环之后(尽管,如果你有带析构函数的块范围变量,情况可能会更复杂);您的解决方案不一定被编译器识别为等效的。

    您实际上可以在这里看到 gcc 一路生成移动n到的代码i,而在第二种情况下,它直接跳出循环。

在风格方面:

  • 我发现“你的方式”过于复杂而不是惯用的——如果我在实际代码中遇到它,我会问自己“为什么他不只使用一个break?”,然后检查两次以确保它不像我'我错过了一些副作用,并且意图实际上只是跳出循环;
  • 正如其他人所说,您的内部分配存在与实际循环条件不同步的风险;
  • 当循环条件变得比简单的范围检查更复杂时,它不会扩展,无论是在逻辑方面(如果循环条件复杂,那么欺骗它可能会变得更复杂)和性能方面(如果循环条件很昂贵)并且您已经知道要退出您不想再次检查它);这也可以通过添加一个额外的变量来规避(这通常是在没有 的语言中完成的break),但这又是对您的算法实际执行的额外干扰;
  • 它根本不适用于基于范围的循环。