部分开始循环

时间:2013-11-15 18:19:10

标签: c++ loops

如果我有一个条件循环,它应该表现得像是从中途开始,那么最好的编码方法是什么呢?包含goto之类的代码是否可以接受以下代码段?

goto first_itr;
do {
  doSomeStuff();
first_itr:
  doSomeOtherStuff();
} while(condition);

我能看到的明显效率较低的替代方案是在doSomeStuff();周围引入一个标志和一个条件,产生以下内容:

bool first = true;
do {
  if(first)
    first = false;
  else
    doSomeStuff();
  doSomeOtherStuff();
} while(condition);

这是我在这种情况下通常使用的方法。可以依靠编译器通过有效地将其转换为第一个片段来改善它吗?

我可以想到的其他替代方案可以避免使用goto,条件会涉及重复代码,但这似乎比goto更糟糕的代码味道。

另外,如果循环对性能至关重要,那么答案是否会有所不同,额外条件的开销会显着降低性能?

5 个答案:

答案 0 :(得分:5)

也许是这样的:

for (;;)
{
    doSomeOtherStuff();
    if (!condition) break;
    doSomeStuff();
}

如果A = doSomeStuff();,B = doSomeOtherStuff();,c表示条件测试,那么我们想要编码

BcABcABcABcABc ...

这可以通过循环遍历ABc的块(并在第一次迭代中以某种方式避免A)来完成,就像问题或块BcA一样,如此解决方案中那样。这种解决方案优于其他所有解决方案的优势在于它避免了代码重复,这种代码重复是众所周知的维护。

答案 1 :(得分:4)

我可能会在循环之前重复doSomeOtherStuff()(你必须在函数中使用它),但是@Kerrek SB的解决方案也很好(特别是如果你不想在函数中使用它)。这与风格无关。

doSomeOtherStuff();
while(condition){
  doSomeStuff();
  doSomeOtherStuff();
}

答案 2 :(得分:1)

随着你的更新:

如果您希望在第一次迭代中跳过函数调用,只需将其从循环结构中删除即可。没有必要在循环中粘贴不需要的条件:

doSomeOtherStuff(); // your first iteration is outside the loop
do
{
    doSomeStuff(); // all other iterations inside the loop
    doSomeOtherStuff();
} while (condition);

如果doSomeOtherStuffcondition产生影响,则应将其重写为:

doSomeOtherStuff(); // your first iteration is outside the loop
while (condition)
{
    doSomeStuff(); // all other iterations inside the loop
    doSomeOtherStuff();
}

这假设操作的顺序很重要(例如,如果函数在数组中的元素上运行,并且您只希望第一个元素被其中一个函数修改)。如果它不重要(例如,您只想分别运行XX-1次函数),您可以使用Antti或Kerrek的解决方案。

答案 3 :(得分:1)

goto是允许的,虽然丑陋。但是,您无法与goto交叉初始值设定项。除此之外,据我所知,在C ++中允许goto进入一个块。

作为一个for循环,重复代码已经建议完成,我开玩笑地建议在这里滥用逗号运算符(假设operator,没有为doSomeOtherStuff()的返回值重载):

while (doSomeOtherStuff(), condition) {
    doSomeStuff();
}

如果A = doSomeStuff()B = doSomeOtherStuff()C = condition,则会导致序列BCABCABC...与原始代码相同;它也会在C第一次评估为false时结束。这是你可以写doSomeOtherStuff()作为表达式。然而,Kerrek SB的for循环几乎肯定是一个更好的答案。

答案 4 :(得分:0)

虽然我已经接受了Kerrek SB的答案,但我还是想为了完整性而添加这个其他答案(也是由于Duff's device的扭曲调整)。它(技术上)不使用goto并且它不会重复代码,尽管良好实践的可读性和使用是值得怀疑的。

switch(true) {
case false:
  do {
    doSomeStuff();
case true:
    doSomeOtherStuff();
  } while(condition);
}