C++数组指针[]或++

C++ array pointers [] or ++

本文关键字:数组 指针 C++      更新时间:2023-10-16

假设我想遍历一个双精度数组并求和。我有两种方法。

A)

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

B)

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

哪个更好,为什么/什么时候应该使用一个而不是另一个。

这是可读性的问题,不应该影响性能。我认为B是最可读的,因此更可取。

我还可以提出第三种变体,它是基于范围的(注意beginend参数):

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

在许多情况下,这是惯用的C++,并且更容易概括。这并不是说总是更可取,它只是可读性和可维护性问题中的另一个变体。

我也会选择样式B,但您应该更喜欢标准算法而不是显式循环:

#include <numeric>
double sum(const double* const series, const int size) {
    return std::accumulate(series, series + size, 0.0);
}

两者本质上都不比另一个好;您应该选择使代码意图最清晰的代码。对于任何现代编译器,都应该将它们优化为相同的机器代码。


但是,请注意,在C++中,将原始指针传递到原始数组被认为是糟糕的风格。考虑使用容器类,如std::vector

在使用现代优化编译时,性能应该没有什么不同。

早在1978年,第一种方法在PDP-11上速度更快,因为间接自动递增寻址需要更少的处理周期,而且没有能够将索引+偏移量转换为自动递增的优化器。

p.S.设置series -= size;没有效果,因为series是按值传递的。

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; 
}