我一直在阅读一个book,它说通过指针算法访问数组元素要比[]运算符快得多。简而言之,this代码比this代码更快。 这本书没有说明原因。即使它提供了显着的速度改进,是否可以使用这种指针算法?
#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页,最后一行
指针访问方法比数组索引快得多。
答案 0 :(得分:5)
即使存在性能差异,x[12]
对*(x + 12)
的清晰度也更为重要。
答案 1 :(得分:2)
数组索引只是指针算术的语法糖。您的编译器会将a[i]
归结为*((a) + (i))
。同意,远离那本书!
有关更深入的解释,请参阅
答案 2 :(得分:2)
完全没有区别,如果我们转到draft C++ standard部分5.2.1
订阅段 1 说(强调我的):
[...] 表达式E1 [E2]与*((E1)+(E2))相同[注:有关*和*的详细信息,请参见5.3和5.7 +和8.3.4有关数组的详细信息。 - 后注]
答案 3 :(得分:1)
垃圾。普通阵列上的a[x]
衰减为*(a + x)
。字面上会有0个性能差异。
答案 4 :(得分:1)
这本书是完全错误的 - 特别是如果这些是他们给出的实际例子。体面编译器可能会为这两种方法生成相同的代码,即使没有优化也会产生相同的性能。
如果没有优化,或者使用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
之类的指令(加载有效地址)因此,即使在汇编级别,索引版本也可能不会更慢(实际上可能更快,因为它避免了循环携带的依赖性,并且更适合于别名分析)。
答案 5 :(得分:-1)
你的两个表格是相同的,你并没有真正做指针运算。
指针形式为:
double * array= new double[10000000] ;
double * dp= array ;
for ( int i= 0 ; ( i < 10000000 ) ; i ++, dp ++ )
{
* dp= 0 ;
}
听到,dp
中的地址通过添加移动到下一个地址。在其他形式中,通过乘以i
时间sizeof(double)并将其添加到array
,每个地址都会计算出地址。它的乘数在历史上比加法慢。