Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用指针递增1的数组元素进行迭代是否更快?_C++_C_Arrays_Pointers_Optimization - Fatal编程技术网

C++ 使用指针递增1的数组元素进行迭代是否更快?

C++ 使用指针递增1的数组元素进行迭代是否更快?,c++,c,arrays,pointers,optimization,C++,C,Arrays,Pointers,Optimization,做这样的事情快吗 for ( int * pa(arr), * pb(arr+n); pa != pb; ++pa ) { // do something with *pa } (大小k=0;k测量,证明,然后问!为什么你会期望一个现代C++编译器不为完全相同的代码优化??你的代码在C中是非法的,请删除[c]标签,或者编辑代码为有效C。 compute1(int*, int): testl %esi, %esi jle .L4 leal -1(%rs

做这样的事情快吗

for ( int * pa(arr), * pb(arr+n); pa != pb; ++pa )
{ 
   // do something with *pa
}

(大小k=0;k { //用arr[k]做点什么 }


我知道
arr[k]
相当于
*(arr+k)
,但在第一种方法中,您使用的是递增1的当前指针,而在第二种情况下,您使用的是从
arr
递增的指针。也许硬件有增加1的特殊方法,所以第一种方法更快?还是不?只是好奇。希望我的问题有意义

这是无法回答的。这取决于编译器和机器

一个非常幼稚的编译器会将代码原样翻译成机器代码。大多数机器确实提供了非常快速的增量操作。它们通常还为带有偏移量的地址提供相对寻址。这可能需要比绝对寻址多几个周期。因此,是的,带有指针的版本可能会更快


但要考虑到每台机器都是不同的,只要程序的可观察行为不变,编译器就可以进行优化。考虑到这一点,我建议一个合理的编译器将从两个版本创建性能没有差异的代码。

如果编译器足够智能(大多数编译器都是),那么两个循环的性能应该相等

例如,我在gcc 5.1.0中编译了生成程序集的代码:

int __attribute__ ((noinline)) compute1(int* arr, int n)
{
  int sum = 0;
  for(int i = 0; i < n; ++i)
  {
    sum += arr[i];
  }
  return sum;
}

int __attribute__ ((noinline)) compute2(int* arr, int n)
{
  int sum = 0;
  for(int * pa(arr), * pb(arr+n); pa != pb; ++pa)
  {
    sum += *pa;
  }
  return sum;
}
如您所见,两个函数中最重的部分(循环)相等:

.L9:
    addl    (%rdi), %eax
    addq    $4, %rdi
    cmpq    %rdi, %rdx
    jne .L9
    rep ret
但在更复杂的示例或其他编译器中,结果可能不同。因此,您应该对其进行测试和度量,但大多数编译器都会生成类似的代码


完整的代码示例:

任何合理的编译器都会为这两个选项在循环中生成相同的代码-我查看了在
std::vector
上迭代生成的代码,使用for循环和整数作为迭代器,或者使用
for(auto I:vec)
类型构造[
std::vector
内部有两个指针用于存储值的
begin
end
,就像您的
pa
pb
]一样。gcc和clang在循环本身内部生成相同的代码[循环的确切细节在编译器之间有细微的差别,但除此之外,没有差别]。循环的设置有细微的差别,但除非您经常执行少于5项的循环[如果是这样,您为什么担心?],否则循环的实际内容才是重要的,而不是实际循环之前的位


与所有性能重要的代码一样,确切的代码、编译器品牌和版本、编译器选项、处理器品牌和型号将对代码的性能产生影响。但对于绝大多数处理器和编译器,我认为没有可测量的差异。如果代码真的很关键,请测量不同的替代方案,并使用E:在你的情况下,什么是最有效的。< /P>测量,证明,然后问!为什么你会期望一个现代C++编译器不为完全相同的代码优化??你的代码在C中是非法的,请删除[c]标签,或者编辑代码为有效C。
compute1(int*, int):
    testl   %esi, %esi
    jle .L4
    leal    -1(%rsi), %eax
    leaq    4(%rdi,%rax,4), %rdx
    xorl    %eax, %eax
.L3:
    addl    (%rdi), %eax
    addq    $4, %rdi
    cmpq    %rdx, %rdi
    jne .L3
    rep ret
.L4:
    xorl    %eax, %eax
    ret
compute2(int*, int):
    movslq  %esi, %rsi
    xorl    %eax, %eax
    leaq    (%rdi,%rsi,4), %rdx
    cmpq    %rdx, %rdi
    je  .L10
.L9:
    addl    (%rdi), %eax
    addq    $4, %rdi
    cmpq    %rdi, %rdx
    jne .L9
    rep ret
.L10:
    rep ret
main:
    xorl    %eax, %eax
    ret
.L9:
    addl    (%rdi), %eax
    addq    $4, %rdi
    cmpq    %rdi, %rdx
    jne .L9
    rep ret