Правила программирования на С и С++. Главы 7-8
Страница 7. Используйте указатели вместо индексов массива


 

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

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

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() является встроенной функцией С++, то накладные расходы на вызов функции могут быть минимальными и есть смысл использовать указатель, поэтому вы можете возразить, что вариант с указателем лучше, ибо накладные расходы тяжело определить.

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

 
« Предыдущая статья   Следующая статья »