C++中的数组函数

  C++中函数拥有参数与参量,也就是实参与形参。
  在研究数组函数之前先看一下基本型变量在函数中的表现:

int	argument = 100;//定义一个实际变量
int function1(int parameter);//声明函数
int main()
{
	int a = function1(argument);
	……
}

  显然声明函数中的变量parameter是形参,C++中通常称之为参量;调用函数时的变量argument是实参,C++通常称之为参数。在函数调用的过程中值在参数与参量之间存在一个名叫值传递的过程:当function1()函数被调用时,编译器会生成一个新变量parameter,随后先前被赋值的argument将自己的值赋给parameter,然后parameter进入function1()函数中进行工作。值传递过程说明了C++程序调用时变量运作的机制:实参(参数)实际上是不进入被调用的函数工作的,它将自己的值拷贝一份给形参(参量),然后形参(参量)进函数开始工作,形参(参量)在函数里怎么折腾,实参(参数)的值也不会有变化。
  如果参数与参量都是数组的话,那么函数调用时的值传递还会和基本型变量一样么?带着这个问题来看一下数组函数的使用。以下代码为一个基础的数组累加函数调用:

#include <iostream>
const int size=9;//定义数组长度
int sum_arr(int arr[],int n);//声明数组累加函数

int main()
{
	using namespace std;
	int OneArray[size]={1,2,3,4,5,6,7,8,9};
	int sum=sum_arr(OneArray,size);//调用函数
	cout<<"Sum:"<<sum<<endl;//打印累加和的值
	cin.get();//按一个按键后退出
	return 0;
}

int sum_arr(int arr[],int n)
{
	for(int i=0;i<n;i++)
	{
		total=total+arr[i];
	}
	return total; 
}

  函数运行结果无需赘述,这里仔细观察数组函数的写法:

int sum_arr(int arr[],int n)
{
	for(int i=0;i<n;i++)
	{
		total=total+arr[i];//数组元素累加和
	}
	return total; 
}

  该函数传入了两个参数,一个是arr[],一个是n。n好理解,n就是参数数组本身的长度。arr[]传递的是什么呢?虽然在函数内部arr直接当做数组进行使用,但是这里需要明白arr并不是一个数组,而是一个指针。
  C++将数组名称视为指针,并且将其解释为数组中第一个元素的地址,即:

OneArray == &OneArray[0];

  OneArray是数组名,OneArray也就是第一个元素的地址,因此可以得出数组函数传递的是一个地址。OneArray内元素的类型都为int,那么OneArray的类型也一定是个int指针,也就是int *。综上,原先的数组函数函数头可以改写为:

int sum_arr(int *arr,int n)

  这里需要注意,C++中只有在函数头与函数原型中,int *arr与int arr[]的含义才相同。在其余场合下这两种表达显然是不能等价的。在函数中可以直接使用arr[i],同时也可以用指针表示法表示数组:

arr[i] == *(arr + i);//某元素的值
&arr[i] == arr +i;//某元素的地址

  知道数组函数怎么写了,继续研究一下数组函数的值传递是如何实现的。显然,参数数组与参量数组的元素值与排列应该是没有区别的,为了观察值传递的本质,在程序中稍微修改一下,观察参数数组与参量数组的首地址与长度。代码如下:

#include <iostream>
const int size=9;//数组长度
int sum_arr(int arr[],int n);//数组累加函数

int main()
{
	using namespace std;
	int OneArray[size]={1,2,3,4,5,6,7,8,9};
	cout<<OneArray<<"=argument array address,";//打印参数(argument)的地址
	cout<<sizeof OneArray<<"=size of argument array"<<endl;//打印参数的地址
	int sum=sum_arr(OneArray,size);
	cout<<"Sum:"<<sum<<endl;//打印累加和的值
	cin.get();//按一个按键后退出
	return 0;
}

int sum_arr(int arr[],int n)
{
	using namespace std;
	int total=0;
	cout<<arr<<"=parameter array address,";//打印参量(parameter)的地址
	cout<<sizeof arr<<"= size of parameter array"<<endl;//打印参量的长度
	for(int i=0;i<n;i++)
	{
		total=total+arr[i];
	}
	return total; 
}

  代码跑出的结果如下:
在这里插入图片描述
  代码跑出来的结果比较吓人,这里仔细分析一下结果意味着什么:首先第一列,参数数组与参量数组的首地址一模一样,这也意味着参数数组和参量数组实际上是一个数组,这和基本类型函数的值传递可截然相反。基本类型函数的参数与参量是两个变量,因此地址一定不同;数组函数的参数数组与参量数组首地址相同,说明编译器并没有创建一个新的参量数组并将参数数组的值赋给它,而是直接把参数数组拿去给函数用了。
  第二列中,参数数组的长度是4*9=36,正常;参量数组的长度是4,这个相对好理解,因为参量数组的arr只是一个int型指针,虽然它的首地址与参数数组相同,但它本身只是个记录首地址的指针罢了,因此只有4个字节。这里也可以看出为什么数组函数还要傻傻地人为赋值数组长度,因为它确实不知道数组是多长。
  经过分析可以得出数组函数被调用时得到的是数组的类型、长度与数组的首地址。函数调用的时候也存在值传递过程,只不过是传递的是首地址,而不是数组的内容。
  数组函数的使用暴露出一个问题,就是函数直接使用原始数据,造成误操作的风险比较大。诚然我们可以用const修饰参数数组令其内容无法改变,但是写代码不能简单的一棍子敲死,数组的内容是否改变需要看具体需求的,我们尽量做到的是在不需要修改内容的部分为其增加“安保措施”。
  最为简单高效的安保措施就是修改函数头:

int sum_arr(const int arr[],int n)
int sum_arr(const int *arr,int n)

  该声明方式牵扯到另一个概念就是const指针,关于指针今后可能会开文章细说(又挖坑了)。在这里意味着对于arr这个指针来说,它认为自己指向的是一个常量数组(到底是不是,无所谓),因此它无法修改数组内的值。也就是说,在sum_arr函数中,参数函数被视作只读数据,如果在该数组函数中执行类似如下所示的语句,编译器将自动报错:

arr[i] +=10;

  在不需要改写数组内容的数组函数中,建议都采用const指针做好保护措施。

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值