是否值得声明作为参数传递的数组的(常量)大小
Is it worth declaring the (constant) size of an array that is passed as an argument?
const int N = 100;
void function1(int array[]){
// ...
}
void function2(int array[N]){
// ...
}
int main(int argc, char *argv[]){
int a[N] = {1, 2, 3, ... , 100};
function1(a);
function2(a);
return 0;
}
我想知道由于某种类型的C++编译器优化(例如,编译器在编译时计算出sizeof(array)
),function2
是否有可能比function1
更快。
对于 C,之前已经讨论过相同的主题:我应该声明作为函数参数传递的数组的预期大小吗?
谢谢!
两个版本的函数之间应该没有任何性能差异;如果有的话,可以忽略不计。但是在你的function2()
中,N 没有任何意义,因为你可以传递任何大小的数组。函数签名不会对数组大小施加任何约束,这意味着您不知道传递给函数的数组的实际大小。尝试传递大小50
数组,编译器不会生成任何错误!
要解决这个问题,你可以将函数写成(它接受一个类型为 int
的数组,大小正好是 100!
const int N = 100;
void function2(int (&array)[N])
{
}
//usage
int a[100];
function2(a); //correct - size of the array is exactly 100
int b[50];
function2(b); //error - size of the array is not 100
可以通过编写一个函数模板来概括这一点,该模板接受对类型为 T
且大小N
数组的引用,如下所示:
template<typename T, size_t N>
void fun(T (&array)[N])
{
//here you know the actual size of the array passed to this function!
//size of array is : N
//you can also calculate the size as
size_t size_array = sizeof(array)/sizeof(T); //size_array turns out to be N
}
//usage
int a[100];
fun(a); //T = int, N = 100
std::string s[25];
fun(s); //T = std::string, N = 25
int *b = new [100];
fun(b); //error - b is not an array!
大多数编译器的两个代码通常会将指向数组的指针作为堆栈(或指定寄存器中的)的函数参数传递......其他任何事情都需要将数组的数据复制到堆栈上函数激活记录的参数部分,这根本不会很快。
因此,例如,对于一个 6 个整数的数组,这两个实现在程序集中看起来像下面这样,该数组在调用 function1
或 function2
的函数的范围内是本地的:
leal -24(%ebp), %eax //store the address of the array in EAX
pushl %eax //push the address on the stack as the first argument
call function1 //call function1 (or function2)
在function1
或function2
中,访问数组将像任何其他指针一样完成。 例如,int sum = array[0] + 5;
的汇编代码如下所示:
movl 8(%ebp), %eax //get the pointer to the array off the stack
movl (%eax), %eax //dereference array[0] and store in EAX
addl $5, %eax //add 5 to the value in EAX
movl %eax, -4(%ebp) //store in "sum", which is at [EBP - 4] on the stack
我不认为明确传递大小有任何区别,因为它没有在任何地方收到,最终会丢失。人们仍然可以超越数组的限制进行访问。通常,我遵循的最佳做法是将大小作为单独的参数传递。
void doSomething(int *ptrary,int size)
{
}
不会有速度差异,但是声明大小可能出于另外两个原因而有用,一个是它将作为其他人的文档。另一个原因是,如果您将其声明为引用参数(如 Nawaz 建议的那样,只是没有模板化),它将防止其他人传入太小的缓冲区,这很棒!缺点是它还将防止传递太大的缓冲区。
- 在调用接收数组的方法时,模板化数组大小是不是一种糟糕的做法
- 在C++中传递给函数时,为什么要指定数组大小作为参数
- C++编程从外部文本文件定义数组大小
- 在C++中使用变量而不是"#define"来指定数组大小是不是一种糟糕的做法?(C错误:在文件范围内
- 从用户那里获取数组大小的值
- 为什么数组大小信息可用于"sizeof"运算符和 delete[] 运算符,但在将数组作为参数传递到
- C++中数组大小未知的指针转换
- 如何在子类中重新定义数组大小?
- 为什么我的 cpp 数组大小是 4 的倍数?
- 尝试将数组大小调整为 -1
- 有没有办法根据命令行参数定义数组大小?运行时与编译时实例化?
- 表达式必须具有常数值,变量不能用作定义数组大小的常数
- 数组大小由输入文件中的行数定义
- Sizeof返回的是指针大小,而不是数组大小.有其他方法可以找到尺寸吗
- 数组大小超过函数大小(C++)
- 当数组大小在C++中未知时,如何在运行时将对字符串数组的引用作为函数参数传递?
- 根据模板值确定的静态数组大小
- 如何从枚举类值中指定模板函数参数中的数组大小?
- 当删除 [] 指针工作时,为什么无法获得指向的数组大小?
- wchar_t wcscpy_s的数组大小问题