数组的C++指针与[]运算符的比较

C++ pointer comparison with []operator for arrays?

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

我读过一本书,书中说通过指针算术访问数组元素比[]运算符快得多。简而言之,这个代码比这个代码快。这本书没有说明原因。即使这样的指针算法在速度上有显著提高,使用它是否明智?

#include <iostream>
using namespace std;
int main() {
// your code goes here
double *array = new double[1000000];
for(int i = 0; i < 1000000; i++)
{
array[i] = 0;//slower?
}
delete[] array;
return 0;
}
#include <iostream>
using namespace std;
int main() {
// your code goes here
double *array = new double[1000000];
for(int i = 0; i < 1000000; i++)
{
*(array + i) = 0;//faster?
}
delete[] array;
return 0;
}

编辑:

引用第369页,倒数第二行

指针访问方法比数组索引快得多。

不,它们完全是一回事。我绝对建议你尽快放下那本书,再拿起一本。

即使存在任何性能差异,x[12]相对于*(x + 12)的清晰度也要重要得多。

数组索引只是指针运算的语法糖。您的编译器将把a[i]归结为*((a) + (i))。同意了,滚出那本书!

有关更深入的解释,请参阅

  1. SO回答
  2. Eli Bendersky的解释

如果我们进入C++标准草案5.2.1订阅段落1说(emphasis mine):

[…]表达式E1[E2](根据定义)与*((E1)+(E2))相同[注意:*和+的详细信息请参见5.3和5.7,数组的详细信息见8.3.4。--尾注]

Utter垃圾。平面阵列上的CCD_ 6衰减为CCD_。实际上将存在0性能差异。

这本书完全错了——尤其是如果这些是他们给出的实际例子。即使没有优化,体面的编译器也可能为这两种方法生成相同的代码,并且它们将具有相同的性能。

如果没有优化,或者使用80年代的编译器,某些类型的指针算术可能会出现性能差异,但示例甚至不能代表这种情况。这些例子基本上只是同一事物的不同语法。

以下是一个可能存在性能差异的示例(与不变的数组索引情况相比):

int main() {
// your code goes here
double *array = new double[1000000], *ptr = array;
for(; ptr < array + 1000000; ptr++)
{
*ptr = 0;
}
return 0;
}

在这里,您不是每次通过循环都对基指针进行索引,而是每次都递增指针。理论上,可以避免索引中隐含的乘法运算,从而实现更快的循环。在实践中,任何像样的编译器都可以将索引形式简化为加法形式,并且在现代硬件上,索引所隐含的sizeof(double)的乘法通常是免费的,作为lea(加载有效地址)等指令的一部分,因此,即使在程序集级别,索引版本也可能不会更慢(事实上可能更快,因为它避免了循环携带的依赖性,并且也更好地进行混叠分析)。

您的两个表单是相同的,您实际上并不是在进行指针运算。

指针形式为:

double * array= new double[10000000] ;
double * dp= array ;
for ( int i= 0 ; ( i < 10000000 ) ; i ++, dp ++ )
{
* dp= 0 ;
}

听说,dp中的地址通过添加移动到下一个地址。在其他形式中,地址是通过乘以i时间大小(double)并将其添加到array来计算的。从历史上看,乘法比加法慢。