2012-02-25 4 views
5

позволяет сказать, что я хочу перебирать массив из двух пар и суммировать их. У меня есть два способа сделать это.Указатели массива C++ [] или ++

)

double sum (double * series, int size) { 
    double sum = 0.0; 
    for (int i = 0; i < size; i++) { 
     sum += *series++; 
    } 
    return sum; 
} 

Б)

double sum (double * series, int size) { 
    double sum = 0.0; 
    for (int i = 0; i < size; i++) { 
     sum += series[i]; 
    } 
    return sum; 
} 

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

+0

Мне нравится B), потому что это короче и легче понять, если вы не знаете, как работают указатели. Вы можете использовать векторы с std :: accumulate. – chris

+0

Стиль A не так ясен для меня, что вы делаете. Лично я всегда выбираю стиль B, исходя из фона C#. –

+0

@ Рихард Дж. Росс III, '* series' оценивает данные, содержащиеся в том, что указывает серия. Цикл увеличивает шаг, поэтому он каждый раз указывает на следующий элемент в массиве. – chris

ответ

6

Это вопрос читаемости, он не должен влиять на производительность. Я думаю, что B является наиболее читаемым и, следовательно, предпочтительным.

Я мог бы также предложить третий вариант, который является диапазоном на основе (обратите внимание на begin и end параметров):

double sum (double* begin, double* end) { 
    double sum = 0.; 
    for (double* it = begin; it != end; ++it) { 
     sum += *it; 
    } 
    return sum; 
} 

Это идиоматично C++, во многих случаях и обобщает более легко. Это не значит, что всегда предпочтительнее, это еще один вариант в вопросе о читаемости и ремонтопригодности.

+0

Да, это в основном то, что std :: накапливает с векторами. – chris

+0

Будем надеяться, что 'begin'' <'' end'. Что произойдет, если 'begin'' == '' end'? –

+1

@SimonWright: Тогда он не войдет в цикл и сразу вернет 0. Условие петли проверяется перед тем, как войти в тело :) –

4

Ни одна из них не лучше, чем другая; вы должны выбрать то, что делает ваш код четким. С любым современным компилятором они должны быть оптимизированы для идентичного машинного кода.


Однако следует отметить, что огибают сырья указателей на сырье массивов считается плохим стилем в C++. Рассмотрим использование класса контейнера, такого как std::vector.

1

С точки зрения производительности не должно быть разницы при использовании современных оптимизирующих компиляций.

Еще в 1978 году первый путь был несколько более быстрым на PDP-11, поскольку косвенная автоинкрементная адресация требовала меньше циклов для обработки, и не было оптимизаторов, способных конвертировать индекс + смещение в автоинкремент.

P.S. Значение series -= size; не действует, потому что series передается по значению.

+0

серия - = размер; устанавливает серию, чтобы сразу вернуться к первому элементу? –

+1

@PatrickLorio Да, но он делает это на * копии * указателя, который передается по значению. Поскольку вы возвращаетесь на следующую строку без доступа к «сериям» после назначения, это присвоение не имеет никакого эффекта. Было бы разумно, если бы вы использовали этот указатель * снова *, например, чтобы найти самый большой или самый маленький элемент в дополнение к поиску суммы. – dasblinkenlight

+3

@PatrickLorio Это не имеет значения. Поскольку фактический указатель, переданный в, передается по значению, когда вы '- =' размер, он не влияет на переменную, которая была передана изначально. –

5

я бы выбрал стиль B, а также, но тогда вы должны предпочесть стандартные алгоритмы над явными петлями:

#include <numeric> 

double sum(const double* const series, const int size) { 
    return std::accumulate(series, series + size, 0.0); 
} 
0

C++ 11 образом, чтобы перебирать массив (если вы не хотите, чтобы просто сумма они и скапливаются не соответствует вашим потребностям) является:

double sum (const double * series, int size) { 
    double sum = 0.0; 
    for_each (series, series + size, [&](double v) { 
     sum += v; 
    }); 
    return sum; 
} 

Обратите внимание, что если вы использовали вектор или список вы получите довольно много и тот же код:

double sum (const vector<double>& series) { 
    double sum = 0.0; 
    for_each (begin(series), end(series), [&](double v) { 
     sum += v; 
    }); 
    return sum; 
} 
Смежные вопросы