您的位置:首页 > 编程语言 > C语言/C++

C++学习 - 数组参数传递及编程技巧

2015-09-18 22:06 302 查看
数组形参
形参的长度会引起误解

数组实参
通过引用来传递数组

多维数组的传递

传递给函数的数组处理
标记结束

标准库方法

显示传递数组大小

在C++中传递数组参数是一件很简单的事情,但是这里面也有一些需要注意的细节,不能忽视,(只能说C++太难了,也太好玩了)。

数组形参

在这个里面,数组是作为形参传递的,有以下几种:

void printArr(int*) {/* ... */}

void printArr(int []) {/* ... */}

void printArr(int [10]) {/* ... */}


这三种达到的目的是一样的,也是等价的,都会被看做
int *


形参的长度会引起误解

编译器会忽略任何数组形参指定的长度的,根据数组的长度(权且这样说),可以在函数内部遍历数组:

void printArr(const int a[10]){
for(size_t i = 0; i != 10; i++){
cout<< a[i] <<endl;
}
}


这里我们已经知道,编译器会忽略数组的长度,但是我们在形参写了长度,这样我们就默认使用了这个长度(会出现一些不可控的问题)。

例如,如下的调用都是合法的:

int main(){
int i =0, j[2] = {0,1};
printArr(&i); //ok! &i 是 int *, 但是运行会出现越界。
printArr(j); // ok! j 会被转换为 int *, 但是也会越界。
return 0;
}


这里虽然编译没问题,但是调用和运行都是有问题的。

数组实参

和其他类型一样,C++比C多了引用类型,(这里强调一下,标准C99版本的C语言是没有参数引用的)。数组形参可以定义为引用或非引用类型。大部分情况如下,数组以普通的非引用类型用作类型传递,此时数组会悄悄的转换为指针,一般来说,非引用类型的形参会初始化为其相应的实参副本,而在传递数组时,实参是指向数组的第一个元素的指针,形参是复制了指针的值,改变的是指针指向的值,并没有更改指针本身的值。

通过引用来传递数组

数组形参可以声明为数组的引用,如果形参是数组的引用,编译器不会把数组实参转化为指针,而是传递数组本身,这种情况下,数组大小成为形参和实参类型的一部分,编译器会检查数组的大小。

void printArr(int (&a)[10]) { /* ... */ }
int main(){
int i = 0, j[2] = {0,1}, k[10] = {0};
printArr(&i); // error!
printArr(j); //error!
printArr(k); // ok!
return 0;
}


这个版本,会严格检查数组的大小。

多维数组的传递

在C++中本来没有多维数组,所以其实多维数组,就是数组中的数组。

这里区分下数组指针和指针数组的问题:

1. 数组指针,是指针。
int (*a)[10];


2. 指针数组,是数组。
int *a [10];


详情看我的博客:C++学习 - 数组指针/指针数组.

除了第一维以外的所有维的长度都是元素类型的一部分,必须明确指定。

上面这句话很重要,它说明了传递多维数组参数必须的形式。

例子:

void printArr( int (*a)[10], int rowSize );


上面这个语句,括号是省不了的,一定要加上。假如不加的话。

void printArr( int a[][10], int rowSize );


一定要这样写才行。

传递给函数的数组处理

非引用的数组形参,只是检查类型,确保实参是和数组元素具有同样类型的指针,而不会检查实际上是否指向数组指定大小。

有三种常见的办法来保证函数的操作,不会让数据实参越界操作。

标记结束

第一种是在数组本身防止一个标记来检测数组的结束,C风格的字符串是以null为结束标记的。

标准库方法

第二种是传递指向数组第一个和最后一个元素的下一个位置的指针,这种变成风格是由标准库所使用的技术。例如:

void printArr(const int *beg, const int *end){
while(beg != end){
cout << *beg++ <<endl;
}
}

int main(){
int j[2] = {0,1};
printArr(j, j+2);
return 0;
}


这种循环很像用
vector
迭代器编写的程序。

显示传递数组大小

第三种方法就是把第二个方法中的结尾指针,变成数组的大小,这种方法在C程序和标准化之前的C++程序是十分普遍的。

void printArr(const int a[], size_t size){
for(size_t i = 0; i != size; ++i){
cout << a[i] << endl;
}
}

int main(){
int j[] = {0,1};
printArr(j, sizeof(j)/sizeof(*j));
return 0;
}


这个版本是用来形参size来确定要输出的元素个数,这样size可以控制访问数组的范围,size不能超过实际大小,程序就能安全运行。

以上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息