|
Программирование >> Решение нетривиальных задач
( p->type )( p ); Главные преимущества такого подхода заключаются в следующем: Вам больше не нужен перечислитель shape type. Функцию print shape() теперь написать гораздо проще. print shape() будет продолжать работать без модификации, когда вы добавите новые фигуры в эту систему. 60. Избегайте циклов do/while Цикл do/while опасен в принципе, так как вы обязательно выполняете его тело хотя бы один раз. Следовательно, вы должны проверить условия завершения до входа в этот цикл. Я часто вижу код, похожий на следующий: if( !проверить нечто ) return ERROR; начинка(); } while( проверить нечто ); Вам гораздо лучше сделать так: while( проверить нечто ) начинка(); Похожий случай: if( некое условие() ) масса материала while( некое условие() && другой материал() ); легче трактовать следующим образом: while( некое условие() ) масса материала if( !другой материал() ) break; Я профессионально занимаюсь программированием с 1979 года и за это время использовал цикл do/while всего два раза. 60.1. Никогда не используйте do/while для бесконечного цикла Код, похожий на следующий: здесь следует несколько страниц кода } while( 1 ); просто заставляет сопровождающего программиста шарить по листингу взглядом, ища while, вместо того, чтобы найти его сразу в случае расположения оператор while (1) в начале цикла. 61. В цикле со счетчиком его значение должно по возможности уменьшаться Циклы являются одним из тех мест, где малое повышение эффективности значительно улучшает выполнение программы, потому что их код выполняется многократно. Так как сравнение с нулем обычно более эффективно, чем сравнение с определенным числом, то цикл с уменьшающимся счетчиком, как правило, выполняется быстрее. Используйте for( i = max; -- i >= 0; ) вместо: for( i = 0; i < max; ++i ) Заметьте, что в обоих случаях счетчики могут быть использованы в качестве действительного индекса массива, что может сделать этот код менее подверженным ошибкам вследствие того, что он ограничивает доступ к массиву его границами. 62. Не делайте одно и то же двумя способами одновременно В качестве контрапункта к предыдущему правилу рассмотрим следующий фрагмент (содержащий в себе ошибку): int array[ARRAY SIZE]; int *p = array; for( i = 1; i < ARRAY SIZE ; ++i ) *p++ = 0; Проблема состоит в том, что счетчик не совпадает по фазе с указателем (i имеет значение 1, когда указатель указывает на элемент array[0]), и последний элемент массива не будет инициализирован. Я обычно предпочитаю для простых перемещений по массивам указатели (вместо индексов массива), потому что указатели, как правило, более эффективны, устраняя неявную операцию умножения в выражении a[i], интерпретируемом как: ( a + ( i* sizeof(a[0]))) Я бы переписал это код таким образом: int array[ARRAY SIZE]; int *current = array; int *const end = array + (SIZE-1); while( current <= end ) *current++ = 0; Так же надежно (хотя и менее эффективно) сделать следующее: int array[ARRAY SIZE]; int i; for( i = 0; i < ARRAY SIZE ; ++i ) array[i] = 0; Кстати, если вы используете указатели, то вам придется извлекать индекс при помощи арифметики указателей, а не за счет сохранения второй переменной. У вас могут возникнуть проблемы, если вы передадите i функции в предыдущем примере с ошибкой. Воспользуйтесь подобным кодом: for( current = array; current <= end; ++current ) { ... f( current - array ); передать функции f() текущий индекс массива С другой стороны, обычно нужно избегать кода, подобного следующему, так как такой оператор цикла чрезвычайно неэффективен: while( (current - array) < ARRAY SIZE ) ... 63. Используйте оператор for, если имеются любые два из инициализурующего, условного или инкрементирующего выражений Иначе используйте while. Такой код: int x = 10; далее следует 200 строк кода, в которых переменная x не
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |