最近,我们发现了一种“好方法”,可以通过使用continue来注释掉代码行:
for(int i=0; i<MAX_NUM; i++){
....
.... //--> about 30 lines of code
continue;
....//--> there is about 30 lines of code after continue
....
}
我问问为什么之前的开发人员将continue关键字放在密集循环中。最有可能的是他/她认为放置“继续”关键字而不是删除所有不需要的代码更容易......
通过查看以下情景,它引发了另一个问题:
情景A:
for(int i=0; i<MAX_NUM; i++){
....
if(bFlag)
continue;
....//--> there is about 100 lines of code after continue
....
}
情景B:
for(int i=0; i<MAX_NUM; i++){
....
if(!bFlag){
....//--> there is about 100 lines of code after continue
....
}
}
您认为哪种方式最好?为什么? break关键字怎么样?
答案 0 :(得分:23)
在这种情况下使用continue
可以大大减少嵌套,并且通常会使代码更具可读性。
例如:
for(...) {
if( condition1 ) {
Object* pointer = getObject();
if( pointer != 0 ) {
ObjectProperty* property = pointer->GetProperty();
if( property != 0 ) {
///blahblahblah...
}
}
}
变得只是
for(...) {
if( !condition1 ) {
continue;
}
Object* pointer = getObject();
if( pointer == 0 ) {
continue;
}
ObjectProperty* property = pointer->GetProperty();
if( property == 0 ) {
continue;
}
///blahblahblah...
}
你看 - 代码变成线性而不是嵌套。
您也可以找到this closely related question的答案。
答案 1 :(得分:6)
对于您的第一个问题,它可能是一种跳过代码而不会将其注释掉或删除它的方法。我不建议这样做。如果您不希望执行代码,请不要在其前面加上continue / break / return,因为这会在您/其他人查看代码时引起混淆,并且可能被视为错误。
至于你的第二个问题,它们基本上是相同的(取决于装配输出)性能,并且很大程度上取决于设计。这取决于您希望代码的读者将其“翻译”为英语的方式,就像大多数人在阅读代码时所做的那样。
所以,第一个例子可能是“Do blah,blah,blah。如果(表达式),继续下一次迭代。” 虽然第二个可能是“请等等,等等,等等。如果(表达),请做等等,等等,等等”
因此,使用if语句的continue可能会破坏其后面的代码的重要性。
在我看来,如果可以的话,我宁愿继续,因为它会减少嵌套。
答案 2 :(得分:4)
对continue
的“评论”使用与goto :-)一样辱骂。放置#if 0/#endif
或/*...*/
非常容易,然后许多编辑器会对注释代码进行颜色编码,因此很明显它不会被使用。 (我有时喜欢例如#ifdef USE_OLD_VERSION_WITH_LINEAR_SEARCH
所以我知道那里留下了什么,因为它对我来说很明显,如果我真的希望有人在编译期间定义它,我就永远不会有这么愚蠢的宏名...猜猜我如果我在该状态下共享代码,则必须向团队解释。)其他答案指出源代码控制系统允许您简单地删除注释代码,而这是我在提交之前的实践 - 通常是“工作”您想要它的阶段,以便最方便地交叉引用,复制粘贴等。
对于场景:实际上,除非你的项目有一个你需要适应的一致方法,否则你使用哪一个并不重要,因此我建议在这种情况下使用哪个看起来更具可读性/表现力。在较长的代码块中,单个继续可能不太可见,因此不太直观,而其中一组 - 或许多分散在整个循环中 - 更难以错过。过度嵌套的代码也会变得丑陋。 因此,如果替代方案开始看起来很吸引人,那么选择其中之一,如果不确定则更改它。
他们也向读者传达了微妙的不同信息:continue
意味着“嘿,排除所有这些情况,然后查看下面的代码”,而if块意味着你必须“推”一个上下文但当你试图理解循环内部的其余部分时,你仍然会想到它们(这里,只是为了找到if紧接着循环终止,所以所有的精神努力都被浪费了。反击这个,继续语句往往会触发一个进行心理检查以确保在下一次循环迭代之前已经完成所有必要的步骤 - 这一切都和下面的循环一样有效,如果有人说在循环的底部添加额外的增量或调试语句,那么他们必须知道他们可能也想继续发表声明。
您甚至可以根据测试的简单程度来决定使用哪个,就像一些程序员将使用早期返回语句来处理异常错误条件一样,但是会对预期的流程使用“结果”变量和结构化编程。一切都变得混乱 - 编程必须至少像问题一样复杂 - 你的工作就是让它变得更简单/更复杂。
为了提高效率,重要的是要记住“不要让小东西流汗”,但在IT中,学习什么是小的可能是一种正确的痛苦: - )。
除此之外:您可能会发现对结构化编程的优缺点进行一些背景阅读是有用的,这涉及单个进入/退出点,getos等。
答案 3 :(得分:4)
我同意其他回答者首次使用continue
是BAD 。 应删除未使用的代码(如果您以后仍需要它,您可以随时从SCM中找到它 - 您确实使用SCM,对吧?: - )
对于第二个,一些答案强调可读性,但我想念一个重要的事情:IMO的第一步应该是将100行代码提取到一个或多个单独的方法。之后,循环变得更短更简单,并且执行流程变得明显。如果我可以将代码提取到单个方法中,我个人更喜欢if
:
for(int i=0; i<MAX_NUM; i++){
....
if(!bFlag){
doIntricateCalculation(...);
}
}
但continue
对我来说几乎同样好。实际上,如果在100行代码中有多个continue
s / return
s / break
,则无法将其提取到单个方法中,因此重构可能最后得到一系列continue
和方法调用:
for(int i=0; i<MAX_NUM; i++){
....
if(bFlag){
continue;
}
SomeClass* someObject = doIntricateCalculation(...);
if(!someObject){
continue;
}
SomeOtherClass* otherObject = doAnotherIntricateCalculation(someObject);
if(!otherObject){
continue;
}
// blah blah
}
答案 4 :(得分:4)
我讨厌注释掉未使用的代码。我做的是,
我完全删除它们,然后签入版本控制。
在源代码控制发明后,谁还需要注释掉未使用的代码?
答案 5 :(得分:4)
continue
在高复杂度循环中非常有用。使用它来注释循环的剩余代码甚至是临时调试是不好的做法,因为人们往往会忘记......
答案 6 :(得分:2)
首先考虑可读性,这将使您的代码更易于维护。使用continue
语句对于用户来说是清楚的:在这种情况下,我不能/想要对此元素做任何其他事情,忘记它并尝试下一个。另一方面,if
只是告诉下一个代码块不适用于那些不满足条件的代码块,但是如果块足够大,你可能不知道是否实际存在任何代码。将适用于此特定元素的其他代码。
由于这个特殊原因,我倾向于选择continue
而不是if。它更明确地说明了意图。