常见传参方式(调用方式):传值传址引用,以及数组引用调用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

传参是c/c++经常用到的,本人在刚开始学习的时候比较困惑,这次在这里总结归纳一下c/c++的各种传参方式


一、一般函数的调用:

函数的调用(参数传递)分为三种:传值调用,传址调用和引用调用,其中引用调用是c++语言中特殊的调用,这种调用是在c语言中没有的。

1.传值调用

(1)特点

调用时系统先计算实参表达式的值,再讲实参按位置赋给形参,也就是对形参的初始化。

(2)实现机制:

系统将实参复制一个副本给形参,在被调用的过程中,形参的改变并不影响实参的改变,也就是说,在内存块中,系统复制实参的数值到另一片内存块,这片内存块就是形参,而如果改变形参的值,也就是改变形参部分内存块的值,对于实参部分内存块并没有什么影响,当函数退出时,形参值将销毁。

(3)代码演示

#include<iostream>
using namespace std;
void swap(int a,int b)
{
	int temp;
	temp=a;
	a=b;
	b=temp;
	cout<<"a="<<a<<",b="<<b<<endl; 
 } 
int main(void)
{
	int a(10);
	int b(20);
	swap(a,b);
	cout<<"a="<<a<<",b="<<b<<endl; 
}

结果:
在这里插入图片描述

2.传址调用

(1)特点

调用时将实参的地址赋给对应的形参指针,使形参的指针指向实参变量。

(2)实现机制:

传值调用是开辟另一块内存块存储实参的值,而传址调用就是开辟另一块内存块存储实参的地址,也就是说,形参就是实参的地址,通过改变形参,而去改变实参的地址,直接去改变实参的值。

(3)代码演示

#include<iostream>
using namespace std;

void swap(int *a,int *b)
{
	int temp;
	temp=*a;
	*a=*b;
	*b=temp;
		cout<<"a="<<a<<",b="<<b<<endl;    //输出地址 
	cout<<"a="<<*a<<",b="<<*b<<endl;
}
int main(void)
{
	int a(10),b(20);
	swap(&a,&b);
	cout<<"a="<<a<<",b="<<b<<endl;
	system("pause");
	return 0; 
 } 

结果:
在这里插入图片描述
可以看到第一行输出的是a和b的地址,而通过输出a和b从而输出a和b的值,而传址调用过后实参的值发生了改变;

3.引用调用

(1)特点

引用调用是c++独有的,简单来说就是给实参起一个别名,通过这个别名去改变实参的值。

(2)实现机制:

使用引用调用时,实参要是变量的变量名,将实参的变量名传递给形参引用,相当于形参直接使用了实参,只不过用的是实参的别名,这种传递方式的好处是不用将实参的值或地址复制给另一个内存块,直接改变实参的值,开销非常小,与传址调用相比而言更好,所以在平时敲代码时推荐使用这种调用方法。

(3)代码演示

#include<iostream>
using namespace std;
 swap(int &x,int &y)
 {
 	int temp;
 	temp=x;
 	x=y;
 	y=temp;
 	cout<<"a="<<x<<"b="<<y<<endl; 
 }
int main(void)
{
	int a(20),b(10);
	int &c=b;                  //这样引用,相当于c是b的别名
	cout<<&b<<endl;
	cout<<&c<<endl;  //验证b和c的地址相同 
	swap(a,b);
	cout<<"a="<<a<<"b="<<b<<endl;
	system("pause"); 
	return 0;
 } 

结果:
在这里插入图片描述
第一行和第二行验证了b和c的地址相同。

二、使用数组作为函数的参数

下面三种方式是当数组调用时的情况,这三种调用方式结果相同,只是调用的机制不同而已,但是在最近学习过程中发现引用调用在特殊情况有妙用。

1.形参实参都是数组

(1)特点

调用和被调用函数的参数都用数组。

(2)实现机制:

这种调用的机制是形参和实参共用内存中的数组,不复制内存块。

2.形参实参都用对应数组的指针

(1)特点

形参和实参都用指针形式

(2)实现机制:

同1,形参和实参共用内存中的数组,不复制内存块。

(3)代码演示

#include<iostream>
using namespace std;
int a[8]={1,3,5,7,9,11,13};
void fun1(int b[],int n)            //第一种调用方式           
{
	for(int i=0;i<n-1;i++)
	{
		b[7]+=b[i];
	}
}
void fun2(int *b,int n)       //第二种调用方式       
{
	for(int i=0;i<n-1;i++)
	{
		*(b+7)+=*(b+i);
	}
}

int main(void)
{
	int m=8;
	fun1(a,m);
	cout<<"数组前七个元素的和:"<<a[7]<<endl; 
	fun2(a,m);	
	cout<<"数组前七个元素之和+第八个元素:"<<a[7]<<endl;            
	fun2(a,m); 
	cout<<"数组前七个元素之和+第八个元素:"<<a[7]<<endl;
	system("pause");
	return 0;
}

结果:
在这里插入图片描述

可以看到这两种调用方法直接改变实参数组元素中的值,

3.形参用引用,实参用数组名

(1)特点

用typedef 定义一个数组类型的别名;再通过别名引用。

typedef char Line[81];
Line text,line;

(2)实现机制及代码演示:

刚开始不太清楚这种定义有什么意义,直到在编译过程中遇到一个问题,举个栗子:
::将数组逆置:
比如规定数组a [5]=1 2 3 4 5,要求输出5 4 3 2 1
如果通过调用函数解决问题,那么传参就会有问题(虽然可以不用这样写也能解这个题,但是就是为了举栗子)

#include<iostream>
using namespace std;
 void f1(int b[]);

int main(void)
{	
	int a[5]={1,2,3,4,5}; 
	int end=sizeof(a)/sizeof(a[0])-1;
	cout<<"传参前数组长度:"<<end<<endl; 
	f1(a);
	system("pause");
	return 0;
 } 
 void f1(int b[])
 {
 	int start=0;
	int end=sizeof(b)/sizeof(b[0])-1;
	cout<<"传参后数组长度:"<<end<<endl; 
	while(start<end)
	{
		swap(b[start],b[end]);
		start++;
		end--;
	}
	cout<<"结果: ";
	for(int k=0;k<5;k++)
	{
		cout<<b[k];
	}	
 }

结果:
在这里插入图片描述
结果错了,最后发现形参之后是数组第一个元素的地址,但是如果用引用调用就能完美解决问题;
代码:

#include<iostream>
using namespace std;

typedef int arr[5];

 void f1(arr &b);
 
int main(void)
{	
	int a[5]={1,2,3,4,5}; 
	int end=sizeof(a)/sizeof(a[0])-1;
	cout<<end<<endl; 
	f1(a);
	system("pause");
	return 0;
 } 
 void f1(arr &b)
 {
 	int start=0;
	int end=sizeof(b)/sizeof(b[0])-1;
	cout<<end<<endl; 
	while(start<end)
	{
		swap(b[start],b[end]);
		start++;
		end--;
	}
	for(int k=0;k<5;k++)
	{
		cout<<b[k];
	}	
 }

这样传参形参的b就是整个数组的字节数而不是第一个元素的字节数。

总结

虽然很简单很基础但是很重要,拿来复习复习也不错。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值