Android C++ 系列:数组在函数中注意事项
1. 背景
数组作为函数形参传递的是数组首元素的地址本来是很简单的知识点,但是在具体使用中还会有一些坑需要注意。
2. 数组做函数形参
C++中数组有两个特殊的性质:
不允许拷贝数组:我们不能将数组的内容拷贝给其他数组作为初始值,也不能用数组为其他数组赋值,所以我们不能以值传递的方式使用数组参数;
使用数组时通常会将其转换成指针,所以我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。
数组做形参的三种写法:
在 C 和 C++中因为数组是以指针方式传递给函数,所以函数中没办法确定数组的实际大小,为了让函数体知道数组大小有以下三种方式:
要求数组本身包含一个结束标记,类似于 C 风格的字符串,用空字符标识数据结尾。但是局限性是数组元素类型和结束标记有明显区分,像 int 数组就不太好把一个数字作为数组的结束标记;
使用标准库规范。这种方法类似于 C++标准库中的 vector 等数据结构的迭代器,传入输入的首元素指针和尾元素指针。
增加一个标记数组大小的 int 型形参,这种最简单直观。
3. 数组引用做函数形参
C++还允许我们将变量定义成数组的引用,同理,形参也可以是数组的引用:
这里涉及到数组的指针和数组的引用的定义:
这几个概念容易混淆。我们这里理解一下:
对于 p,我们把类型修饰符从右向左依次绑定来理解,那么 p 定义的是一个大小为 10 的数组,名字是 p,数组中存放的是指向 int 的指针;
对于 p2,从右向左解释不太合理,这里就要从内向外理解。圆括号括起来的
*p
意味着 p 是一个指针,再看右边我们知道 p 是指向大小为 10 的数组的指针,再看左边,我们知道数组中的元素是 int。
C++这种语法特别绕,有时候感觉勉强解释通了很容易就又混了,倒不如通过熟能生巧来“死记硬背”。
4. 多维数组作为函数的形参
C++本身没有多维数组,我们看到的多维数组其实是数组的数组。
将多维数组传递给函数时,真正传递的是指向数组首元素的指针,而首元素本身又是一个数组,所以形参实际上是一个指向数组的指针,数组的第二维的大小都是数组类型的一部分,不能省略:
p 指向数组的首元素,而这个数组的元素是 10 个整数构成的数组。p 实际是指向含有 10 个整数的数组的指针,注意是 p 是指向指针,指向含有 10 个整数数组的指针,特别绕。
如果我们使用数组的语法定义函数,编译器会忽略掉第一个维度,所以我们最好不要把它包括在形参列表内:
p 看起来是一个二维数组,实际上形参是指向含有 10 个整数的数组的指针,相当于是以为数组。
我们回忆一下我们的 main 函数参数:
或者
第二个参数 argv 是含有指向 C 风格字符串的指针元素的数组。
5. 可变形参
其实数组我们就可以理解成是一种可变形参,具体数量可以通过实参来指定,但是这样有个局限性,就是所有的参数类型必须一致。
C++11 新标准提供了两种可变形参,一种类似于数组,是标准库提供的 initializer_list;还有一种可以类型不同的省略符形参,这种主要是用于 C++和 C 函数的交互接口程序。
6. 总结
本文总结了数组作为函数形参的问题,以及数组指针,数组引用做形参的理解、多维数组作为函数的形参可能遇到的坑。
版权声明: 本文为 InfoQ 作者【轻口味】的原创文章。
原文链接:【http://xie.infoq.cn/article/ef9faf6e4d9016083da7bbc6b】。文章转载请联系作者。
评论