如果我有一个条件循环,它应该表现得像是从中途开始,那么最好的编码方法是什么呢?包含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
更糟糕的代码味道。
另外,如果循环对性能至关重要,那么答案是否会有所不同,额外条件的开销会显着降低性能?
答案 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);
如果doSomeOtherStuff
对condition
产生影响,则应将其重写为:
doSomeOtherStuff(); // your first iteration is outside the loop
while (condition)
{
doSomeStuff(); // all other iterations inside the loop
doSomeOtherStuff();
}
这假设操作的顺序很重要(例如,如果函数在数组中的元素上运行,并且您只希望第一个元素被其中一个函数修改)。如果它不重要(例如,您只想分别运行X
和X-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);
}