用数组或指针引用函数?
Pereferring function with array or pointer?
我有两个函数,其中一个是带有数组的函数,另一个是带有指针参数的函数。它们返回相同的结果,但我不知道哪个更好用。
#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];
}
在这两种情况下,您都是通过引用传递数组,因此没有区别。
您的 sum 函数显然对传入的数组有很多了解。所以我认为最好强制数组是函数所期望的那种。
编辑:如果将 int[][] 类型的变量传入接受 int 指针 (int*( 的函数中,则必须将该变量显式转换为 int*,否则编译器将不接受它。
因此,福尔
int sumA(int a[SIZE][SIZE])
是两者中更好的。
从性能的角度来看,sumB
更好,因为您正在循环展开。要注意的是a
是否是您不检查的 4 的倍数,这可能会导致程序崩溃。
编辑:sumA
当然更好,因为它更严格(它知道确切的尺寸(
第一种解决方案对类型更安全,但对性能不利:
- 循环是按每个字节在内存中添加跳转的顺序,这对缓存不利
- 你必须依靠编译器展开循环,甚至意识到它可以由一个而不是两个来完成
第二种解决方案是手动循环展开,使用分布式和变量可以很好地与 cpu 流水线配合使用(如果一开始没有矢量化(并减少分支。
两者都被矢量化,但第二个更好。 在第一个中,替换循环顺序确实可以改善事情,但不会使生成的程序集相等(虽然它们的速度接近,但第二个要长几倍(。 https://godbolt.org/g/bW1Jkd 我测量了 10 倍的性能差异(大肠杆菌上有 -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];
}
这不是一个复杂的功能,一切仍然易于阅读。
此外,我不认为4
常数应该成为"非魔法",除非展开是完全通用的,但这需要一些模板魔法。 命名一个值应该表明它可以在不完全破坏所有内容的情况下进行更改。
在 2 之间,我将使用更多类型,但使用正确的命名sumB
可能是可行且更通用的:int sumSIZESIZEints(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);
}
- 区分接受常量参数的函数引用/指针和与函数参数同名的非常量参数
- 类 Referention 中C++回调函数引用非静态函数
- 使用函数引用指向节点的指针删除链表中的节点?
- 解释通过从函数引用返回数组的语法
- "Class1"类"Class2"对象作为私有数据成员。如何通过"Class 2"函数引用"Class1"对象?
- 使用默认构造函数引用成员变量初始化错误
- 无法调用函数引用 c++
- 使用 decltype(this) 获取函数引用
- 我应该如何定义返回指针的函数?(引用指针与指针指针)
- 从内联函数引用文件静态变量
- Boost::将sigaction函数引用绑定到实例
- 一种比函数引用更有效的方法
- 奇怪的未定义函数引用,函数调用C++不存在
- 是否可以检测绑定成员函数引用的对象是否被删除或销毁
- 构造函数引用参数导致seg错误
- 是否可以使函数模板从函数引用中获取“decltype”
- 无法让 Lua 函数引用"self"
- 如何解析变量和函数引用(Linker & Compiler)?
- 从不同模块调用函数 - 引用错误
- 如何在主函数中连接到数据库,然后从其他函数引用它