Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.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++ 带数组或指针的传递函数?_C++_Arrays_Pointers - Fatal编程技术网

C++ 带数组或指针的传递函数?

C++ 带数组或指针的传递函数?,c++,arrays,pointers,C++,Arrays,Pointers,我有两个函数,一个是带数组的函数,另一个是带指针参数的函数。它们返回相同的结果,但我不知道哪一个更适合使用 #define SIZE 1024 int sumA(int a[SIZE][SIZE]) { int sum = 0; for(int y = 0; y < SIZE; y++) for(int x = 0; x < SIZE; x++) sum += a[x][y]; return sum; } int sumB(int *a) {

我有两个函数,一个是带数组的函数,另一个是带指针参数的函数。它们返回相同的结果,但我不知道哪一个更适合使用

#define SIZE 1024

int sumA(int a[SIZE][SIZE])
{
  int sum = 0;
  for(int y = 0; y < SIZE; y++)
    for(int x = 0; x < SIZE; x++)
      sum += a[x][y];

  return sum;
}

int sumB(int *a)
{
  int sum[4] = {0, 0, 0, 0};

  for( int i = 0; i < SIZE*SIZE; i += 4 )
  {
      sum[0] += a[i+0];
      sum[1] += a[i+1];
      sum[2] += a[i+2];
      sum[3] += a[i+3];
  }

  return sum[0] + sum[1] + sum[2] + sum[3];
}
#定义大小1024
int sumA(int a[SIZE][SIZE])
{
整数和=0;
对于(int y=0;y
在这两种情况下,都是通过引用传递数组,因此没有区别

显然,sum函数对传入的数组有很多了解。因此,我认为最好强制数组为函数所期望的类型

编辑:如果将int[][]类型的变量传递到接受int指针(int*)的函数中,则必须将该变量显式转换为int*,否则编译器将不接受它

因此

int sumA(int a[SIZE][SIZE])

在这两种情况下,都是通过引用传递数组,因此没有区别

显然,sum函数对传入的数组有很多了解。因此,我认为最好强制数组为函数所期望的类型

编辑:如果将int[][]类型的变量传递到接受int指针(int*)的函数中,则必须将该变量显式转换为int*,否则编译器将不接受它

因此

int sumA(int a[SIZE][SIZE])

是两者中的佼佼者。

sumB
从性能的角度来看是更好的。需要注意的是,
a
是否是4的倍数,如果不进行检查,可能会导致程序崩溃


编辑:
sumA
当然更好,因为它更严格(它知道确切的尺寸)

sumB
从性能的角度来看更好些。需要注意的是,
a
是否是4的倍数,如果不进行检查,可能会导致程序崩溃


编辑:
sumA
当然更好,因为它更严格(它知道确切的尺寸)

第一种解决方案更安全,但对性能不利:

  • 循环的顺序是,后续的循环在内存中按每个字节的大小*sizeof(int)添加跳转,这对缓存不利
  • 您必须依赖于编译器展开循环,甚至意识到它可以由一个而不是两个来完成
  • 第二种解决方案是手动展开循环,使用分布式和变量可以很好地配合cpu流水线(如果一开始没有矢量化的话)并生成较少的分支

    两者都得到矢量化,但第二个更好。 在第一种情况下,替换循环顺序确实可以改善情况,但不会使生成的程序集相等(当它们的速度接近时,第二种情况会延长几倍)。 我测量了10倍的性能差异(在coliru上使用-O3,在gcc上使用),这有利于第二种解决方案)

    因此,我建议将两者混合:

    int sumA(int a[SIZE][SIZE])
    {
      static_assert(SIZE % 4 == 0);
      int* flat_a = &(a[0][0]);
    
      int sum[4] = {0, 0, 0, 0};
    
      for( int i = 0; i < SIZE*SIZE; i += 4 )
      {
          sum[0] += flat_a[i+0];
          sum[1] += flat_a[i+1];
          sum[2] += flat_a[i+2];
          sum[3] += flat_a[i+3];
      }
    
      return sum[0] + sum[1] + sum[2] + sum[3];
    }
    
    intsuma(inta[SIZE][SIZE])
    {
    静态断言(大小%4==0);
    int*flat_a=&(a[0][0]);
    整数和[4]={0,0,0,0};
    对于(int i=0;i
    这不是一个复杂的函数,所有内容都很容易阅读

    另外,我不认为
    4
    常量应该是“非魔法”的,除非展开是完全通用的,这需要一些模板魔法。
    命名一个值应该表明它可以在不完全破坏所有内容的情况下进行更改。

    第一种解决方案更为类型安全,但对性能不利:

  • 循环的顺序是,后续的循环在内存中按每个字节的大小*sizeof(int)添加跳转,这对缓存不利
  • 您必须依赖于编译器展开循环,甚至意识到它可以由一个而不是两个来完成
  • 第二种解决方案是手动展开循环,使用分布式和变量可以很好地配合cpu流水线(如果一开始没有矢量化的话)并生成较少的分支

    两者都得到矢量化,但第二个更好。 在第一种情况下,替换循环顺序确实可以改善情况,但不会使生成的程序集相等(当它们的速度接近时,第二种情况会延长几倍)。 我测量了10倍的性能差异(在coliru上使用-O3,在gcc上使用),这有利于第二种解决方案)

    因此,我建议将两者混合:

    int sumA(int a[SIZE][SIZE])
    {
      static_assert(SIZE % 4 == 0);
      int* flat_a = &(a[0][0]);
    
      int sum[4] = {0, 0, 0, 0};
    
      for( int i = 0; i < SIZE*SIZE; i += 4 )
      {
          sum[0] += flat_a[i+0];
          sum[1] += flat_a[i+1];
          sum[2] += flat_a[i+2];
          sum[3] += flat_a[i+3];
      }
    
      return sum[0] + sum[1] + sum[2] + sum[3];
    }
    
    intsuma(inta[SIZE][SIZE])
    {
    静态断言(大小%4==0);
    int*flat_a=&(a[0][0]);
    整数和[4]={0,0,0,0};
    对于(int i=0;i
    这不是一个复杂的函数,所有内容都很容易阅读

    另外,我不认为
    4
    常量应该是“非魔法”的,除非展开是完全通用的,这需要一些模板魔法。
    命名一个值应该表明它可以在不完全破坏一切的情况下进行更改。

    在这两个值之间,我将使用更多的类型,但是正确命名
    sumB
    可能是可行的,并且更通用:
    int-sumsizeziints(const-int*)

    与您期望的相反,
    sumA
    的一个
    SIZE
    被忽略,导致

    int sumA(int (*a)[SIZE])
    
    更重要的是:

    int sum(const int (&a)[SIZE][SIZE])
    {
        return std::accumulate(&a[0][0], &a[0][0] + SIZE * SIZE, 0);
    }
    

    在2之间,我将使用更多的类型化,但是使用正确的命名
    sumB
    可能是可行的和更通用的:
    int-sumsizeziints(const-int*)

    与你期望的相反,一个