Анимация
JavaScript
|
Главная Библионтека поэтому вместо умножения нельзя использовать более эффективный сдвиг. Вы можете сделать то же самое посредством указателей следующим образом: thing *p = (thing *)array; int n cells = nrows * ncols; while ( --n cells >= 0 ) (p++)->field = 0; При этом здесь вообще нет умножения во время выполнения. Оператор инкрементирования p++ просто прибавляет 12 к p. С другой стороны, указатель лучше только тогда, когда вы можете его инкрементировать, то есть когда вы обращаетесь к последовательным элементам. Если вам нужен по настоящему случайный доступ в массив, то запись с квадратными скобками намного проще читается, и разницы в скорости выполнения нет. Аналогично, если внутренняя часть цикла в принципе неэффективна - скажем, например, мы сделали следующее: for ( row = 0; row < nrows ; ++nrows ) for ( col = 0; col < ncols ; ++cols ) f( array[row][col] ); и f() требует для выполнения две секунды - тогда относительный выигрыш от использования указателей будет существенно перевешен накладными расходами на вызов функции, и, естественно, вы можете утверждать, что квадратные скобки легче читаются. Конечно, если f() является встроенной функцией Си++, то накладные расходы на вызов функции могут быть минимальными и есть смысл использовать указатель, поэтому вы можете возразить, что вариант с указателем лучше, ибо накладные расходы тяжело определить. Наконец, верно, что оптимизатор часто может преобразовать вариант цикла с индексами массива в вариант с указателями, но я думаю, что это плохой стиль - писать неэффективный код в надежде на то, что оптимизатор очистит его после вас. Указатели так же хорошо читаемы, как и индексы массивов, для того, кто знает язык программирования. 89. Избегайте goto, за исключением Правила в этом разделе применяйте только к программам на Си. Оператор goto не должен никогда использоваться в Си++ по причинам, рассмотренным в правиле 54 - существует вероятность того, что конструкторы и деструкторы будет невозможно вызвать. Вообще вы должны избегать оператора goto не потому, что goto - унаследованный порок, а потому что существуют лучшие решения. Язык Си, например, дает вам массу отличающихся от goto способов выхода из циклов. Оператор goto может также ухудшать читаемость. Я на самом деле видел код, подобный нижеследующему, и чтобы разобраться, как он работает, потребовалось полчаса: while (1) while ( условие ) ... while ( другое условие ) метка1: ... goto метка2; ... if ( третье условие ) ... if ( другое условие ) goto метка1; else метка2: ... Но самое интересное, что после того, как я разобрался с этим, стало легко переписать его, исключив переходы goto. Проблема читаемости все же сохраняется, даже если goto в явном виде отсутствует. Оператор switch, например, неявно выполняет goto для перехода к оператору case. Последующий пример вполне законен с точки зрения Си, но я не стал бы его вам рекомендовать: switch( некоторое условие ) case A: if ( некоторое другое условие ) ... else case b: ... Оператор goto полезен в некоторых случаях. Вот два из них: • Множество переходов goto к единственной метке, стоящей перед оператором return, лучше, чем множество операторов return. Такую процедуру легче отлаживать, так как для перехвата выхода из нее вы можете установить единственную точку прерывания. Имейте в виду, что метка должна предшествовать оператору; она не может стоять перед закрывающей фигурной скобкой. При необходимости пользуйтесь следующим приемом: ... exit: return ; • Переходы goto вниз по программе, обеспечивающие выход из системы вложенных циклов, лучше, чем флаг завершения типа "готов", который должен проверяться в каждом операторе управления циклом. Если каждый из операторов while в следующем примере выполнить по 1 00 раз, то флаг "готов" нужно проверить 1 000000 раз, хотя он установлен всего лишь на случай ошибки int готов =0; int условие1, условие2, условиеЗ; ... while (!готов && условие1) while (!готов && условие2) while (!готов && условие3) if ( нечто ужасное ) готов =1; Исключите миллионы ненужных проверок при помощи goto следующим образом: while ( условие1) while ( условие2) while ( условие3) if ( нечто ужасное ) goto выход; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 [ 39 ] 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |