Другой способ использования ключевого слова continue в С++
Недавно мы обнаружили "хороший способ" для комментариев строк кода, используя 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
....
}
}
Как вы думаете, что лучше? Зачем?
Как насчет сломанного ключевого слова?
Ответы
Ответ 1
Использование 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...
}
Вы видите - код становится линейным, а не вложенным.
Вы также можете найти ответы на этот тесно связанный с этим вопрос.
Ответ 2
Для вашего первого вопроса, это может быть способ пропустить код, не комментируя его или не удаляя. Я бы не рекомендовал это делать. Если вы не хотите, чтобы ваш код выполнялся, не переходите к нему с продолжением/перерывом/возвратом, так как это может вызвать путаницу, когда вы/другие просматриваете код и можете быть замечены как ошибка.
Что касается вашего второго вопроса, они в основном идентичны (зависит от производительности сборки), и в значительной степени зависят от дизайна. Это зависит от того, как вы хотите, чтобы читатели кода "переводили" его на английский, так как большинство читает код.
Итак, в первом примере можно прочитать "Do blah, blah, blah. Если (выражение), переходите к следующей итерации".
В то время как второй может читать "Do blah, blah, blah. Если (выражение), делайте blah, blah, blah"
Таким образом, использование continue инструкции if может подорвать важность кода, который следует за ним.
По-моему, я бы предпочел продолжить, если бы мог, потому что это уменьшило бы вложенность.
Ответ 3
Это "комментарий" использования continue
примерно так же оскорбительно, как и goto:-). Так легко поставить #if 0/#endif
или /*...*/
, и многие редакторы затем будут кодировать код с комментариями, поэтому сразу же очевидно, что он не используется. (Иногда мне нравится, например, #ifdef USE_OLD_VERSION_WITH_LINEAR_SEARCH
, поэтому я знаю, что осталось там, учитывая сразу же очевидное, что у меня никогда не будет такого глупого имени макроса, если я действительно ожидал, что кто-то определит его во время компиляции... думаю, я бы должны объяснить это, если я поделился кодом в этом состоянии.) Другие ответы указывают, что системы управления версиями позволяют просто удалить прокомментированный код, и, хотя моя практика перед фиксацией - часто есть "рабочий" этап, вы хотите его для максимально удобной перекрестной ссылки, copy-paste и т.д.
Для сценариев: практически не имеет значения, какой из них вы используете, если у вашего проекта нет последовательного подхода, с которым вам нужно вписаться, поэтому я предлагаю использовать то, что кажется более читаемым/выразительным в данных обстоятельствах. В более длинных блоках кода однократное продолжение может быть менее видимым и, следовательно, менее интуитивно понятным, в то время как группа из них - или многих, разбросанных по всему циклу - сложнее пропустить. Слишком вложенный код может стать уродливым. Поэтому выберите либо, если не уверены, а затем измените его, если альтернатива начнет выглядеть привлекательной.
Они также сообщают читателю тонко другую информацию: continue
означает "эй, исключите все эти обстоятельства, а затем посмотрите на код ниже", тогда как блок if означает, что вам нужно "нажимать" контекст, но все же все они в вашем уме, когда вы пытаетесь понять остальную внутренность цикла (здесь только для того, чтобы найти, если сразу же последовало завершение цикла, поэтому все эти умственные усилия были потрачены впустую. Противодействие этому, продолжающиеся утверждения, как правило, вызывают психическую проверку чтобы все необходимые шаги были завершены до следующей итерации цикла - все это было бы так же справедливо, как и любое последующее, и если кто-то говорит, добавляет дополнительный приращение или команду отладки в нижней части цикла, тогда они должны знать, что есть которые они также могут обрабатывать.
Вы даже можете решить, что использовать, исходя из того, насколько тривиальным является тест, так как некоторые программисты будут использовать ранние операторы возврата для исключительных условий ошибки, но будут использовать переменную "result" и структурированное программирование для ожидаемых потоков. Все может запутаться - программирование должно быть по крайней мере сложным, как проблемы - ваша задача - сделать его минимально более грязным/более сложным, чем это.
Чтобы быть продуктивным, важно помнить "Не потеть мелкие вещи", но в ИТ это может быть правильная боль, узнавая, что мало: -).
Кроме того, вам может показаться полезным сделать некоторые фоновые чтения о плюсах/минусах структурированного программирования, которые включают в себя одиночные точки входа/выхода, gotos и т.д.
Ответ 4
Я согласен с другими респондентами в том, что первое использование continue
- это BAD. Неиспользуемый код следует удалить (если вы все еще нуждаетесь в нем позже, вы всегда можете найти его из своего SCM - вы используете SCM, правильно?: -)
Во-вторых, некоторые ответы подчеркивают читаемость, но я пропускаю одну важную вещь: IMO первым шагом должен быть извлечь 100 строк кода в один или несколько отдельных методов. После этого цикл становится намного короче и проще, а поток выполнения становится очевидным. Если я могу извлечь код в один метод, я лично предпочитаю if
:
for(int i=0; i<MAX_NUM; i++){
....
if(!bFlag){
doIntricateCalculation(...);
}
}
Но a continue
было бы почти одинаково хорошо для меня. Фактически, если в пределах 100 строк кода есть несколько continue
/return
/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
}
Ответ 5
Я ненавижу комментировать неиспользуемый код. Я сделал то, что
Я удаляю их полностью, а затем проверяю на контроль версий.
Кому еще нужно прокомментировать неиспользуемый код после изобретения управления исходным кодом?
Ответ 6
continue
полезен для цикла с высокой степенью сложности. Это плохая практика использовать его, чтобы прокомментировать оставшийся код цикла даже для временной отладки, поскольку люди склонны забывать...
Ответ 7
Сначала подумайте об удобочитаемости, и это поможет сделать ваш код более удобным. Использование оператора continue
ясно для пользователя: при этом условии нет ничего другого, что я могу/не хочу делать с этим элементом, забыть об этом и попробовать следующее. С другой стороны, if
сообщает только, что следующий блок кода не применяется к тем, для которых условие не выполняется, но если блок достаточно большой, вы можете не знать, есть ли на самом деле какой-либо дополнительный код который будет применяться к этому конкретному элементу.
Я предпочитаю использовать continue
по if, если по этой причине. В нем более четко указано намерение.