C++学习 - 数组参数传递及编程技巧
2015-09-18 22:06
302 查看
数组形参
形参的长度会引起误解
数组实参
通过引用来传递数组
多维数组的传递
传递给函数的数组处理
标记结束
标准库方法
显示传递数组大小
在C++中传递数组参数是一件很简单的事情,但是这里面也有一些需要注意的细节,不能忽视,(只能说C++太难了,也太好玩了)。
这三种达到的目的是一样的,也是等价的,都会被看做
这里我们已经知道,编译器会忽略数组的长度,但是我们在形参写了长度,这样我们就默认使用了这个长度(会出现一些不可控的问题)。
例如,如下的调用都是合法的:
这里虽然编译没问题,但是调用和运行都是有问题的。
这个版本,会严格检查数组的大小。
这里区分下数组指针和指针数组的问题:
1. 数组指针,是指针。
2. 指针数组,是数组。
详情看我的博客:C++学习 - 数组指针/指针数组.
除了第一维以外的所有维的长度都是元素类型的一部分,必须明确指定。
上面这句话很重要,它说明了传递多维数组参数必须的形式。
例子:
上面这个语句,括号是省不了的,一定要加上。假如不加的话。
一定要这样写才行。
有三种常见的办法来保证函数的操作,不会让数据实参越界操作。
这种循环很像用
这个版本是用来形参size来确定要输出的元素个数,这样size可以控制访问数组的范围,size不能超过实际大小,程序就能安全运行。
以上。
形参的长度会引起误解
数组实参
通过引用来传递数组
多维数组的传递
传递给函数的数组处理
标记结束
标准库方法
显示传递数组大小
在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不能超过实际大小,程序就能安全运行。
以上。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- C++ Custom Control控件向父窗体发送对应的消息
- C++中拷贝构造函数的应用详解