Правила программирования на Си и Си++


Используйте указатели вместо индексов массива


Вообще, инкрементирование указателя — лучший способ перемещения по массиву, чем индекс массива. Например, простой цикл, подобный следующему, страшно неэффективен:

struct thing

{

   int field;

   int another_field;

   int another_field;

};

thing array[ nrows ][ ncols ];

int row, col;

for (  row = 0;  row nrows ;  ++nrows )

   for (  col = 0;  col ncols;  ++cols )

      array[row][col].field = 0;

Выражение array[row][col]



требует двух умножений и одного сложения во время выполнения. Вот что происходит на самом деле:

array + (row * size_of_one_row) + (col * size_of_a_thing)

Каждая структура имеет размер 12 байтов, и 12 не является степенью 2, поэтому вместо умножения нельзя использовать более эффективный сдвиг.

Вы можете сделать то же самое посредством указателей следующим образом:

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()

является встроенной функцией Си++, то накладные расходы на вызов функции могут быть минимальными и есть смысл использовать указатель, поэтому вы можете возразить, что вариант с указателем лучше, ибо накладные расходы тяжело определить.

Наконец, верно, что оптимизатор часто может преобразовать вариант цикла с индексами массива в вариант с указателями, но я думаю, что это плохой стиль —

писать неэффективный код в надежде на то, что оптимизатор очистит его после вас. Указатели так же хорошо читаемы, как и индексы массивов, для того, кто знает язык программирования.



Содержание раздела