C++函数参数传递(值传递,指针传递,引用传递)

本文详细探讨了C++中函数参数的三种传递方式:值传递、指针传递和引用传递。值传递不会改变原始变量的值,指针传递通过地址操作内存,而引用传递则像别名,直接作用于原始变量。同时,通过函数模板的例子展示了不同类型参数传递的效果,强调了在模板中指针和引用的处理差异。
摘要由CSDN通过智能技术生成

在看这个之前,需要完全搞懂变量,指针,引用的关系和使用,推荐看我的另一篇博客。C++变量,指针,引用详解
本文中我们研究函数模板参数传递,以加深对于传递的不同参数的理解。然后再研究一般函数的参数传递。

一般函数参数传递

//1. 值传递
//1. 值传递
void mySwap01(int num1, int num2) {
	int temp = num1;
	num1 = num2;
	num2 = temp;
}

//2.地址/指针 传递
void mySwap02(int* num1, int* num2) {
	int temp = *num1;
	*num1 = *num2;
	*num2 = temp;
}

//3. 引用传递
void mySwap03(int& num1, int& num2) {
	int temp = num1;
	num1 = num2;
	num2 = temp;
}

int main() {

	int a = 10;
	int b = 20;

	mySwap01(a, b);
	cout << "a:" << a << " b:" << b << endl;

	mySwap02(&a, &b);
	cout << "a:" << a << " b:" << b << endl;
	
	int* point_a = &a;
	int* point_b = &b;
	mySwap02(point_a, point_b);
	cout << "a:" << a << " b:" << b << endl;

	mySwap03(a, b);
	cout << "a:" << a << " b:" << b << endl;

	return 0;
}

输出结果为:

a:10 b:20
a:20 b:10
a:10 b:20
a:20 b:10

从上面代码可以看出,三个函数的参数传递方式分别为,值传递,地址传递,引用传递。
5dd445ab-b1a3-40ec-8ee8-a6e8d182e979

值传递

第一个函数接收的形参是一个整形变量,那么不论怎么操作形参,都不会改变实参的值(实参就是传递的变量)。实质上,我们只是把变量的值复制给形参,实参和形参不会共享相同的存储空间,而是各自有各自的内存空间,所以改变形参的值不会改变实参的值。所以输出结果的第一行a仍然为10,b仍然为20。

地址传递

第二个函数接收的形参是一个指针,指针本身的数据就是内存空间的地址,所以我们在传递参数的时候可以直接传递变量的地址,使用 &+变量 即可。从下面代码可以看出,我们可以直接用地址使用*符号,就像对指针使用 *一样进行解指针操作,可以获取指针指向内存空间的数据内容。实质上指针就是内存空间的地址,所以使用指针和直接使用地址是完全一样的。

再看输出结果第二行,这个时候a和b的值已经对换了,因为第二个函数接收的参数是内存空间地址,使用*符号就可以操作输入实参的内存空间地址,就像下面代码这样,直接对地址使用 *符号。

int main(){
	int a = 1;
	cout << *(&a) << endl;
}

输出结果为:

1

如果这个时候第二个函数在函数内部不使用 *符号进行解指针操作,那么会发生什么呢?看下面代码。因为在函数内部没有使用 *符号,那么就代表我们并没有操作传入实参的内存空间,实际的num1,num2是内存空间的地址,发生交换的是内存空间的地址。这就是说:如果我们想通过地址操作某段内存空间,使其内部的数据发生变化,那么必须使用 * 符号。

void mySwap02(int* num1, int* num2) {
	int* temp = num1;
	num1 = num2;
	num2 = temp;
	cout << "交换后 " << "num1= " << num1 << " num2= " << num2 << endl;
}
int main() {

	int a = 10;
	int b = 20;
	
	mySwap02(&a, &b);
	cout << "a:" << a << " b:" << b << endl;
	
	return 0;
}

输出结果为:

交换后 num1= 0000007F4973FAA4 num2= 0000007F4973FA84
a:10 b:20

指针传递

第二个函数的形参就是一个指针格式,我们当然可以传入指针啦!指针本质上就是内存空间的地址,所以通过 * 符号解指针后就可以操作具体的内存空间,所以最上面代码的输出结果的第三行就发生了a,b值数值变化。
同样的,类似与地址传递,如果第二个函数内部不适用 * 符号,会发生什么呢?从下面代码输出结果可以看出,会发生和地址传递一样的结果,交换的num1,num2是地址,由于没有使用 * 符号,就不会改变实参内存空间的内部具体数据,所以a,b的值仍然没有发生交换。

void mySwap02(int* num1, int* num2) {
	int* temp = num1;
	num1 = num2;
	num2 = temp;
	cout << "交换后 " << "num1= " << num1 << " num2= " << num2 << endl;
}
int main() {

	int a = 10;
	int b = 20;
	
	int* point_a = &a;
	int* point_b = &b;
	mySwap02(point_a, point_b);
	cout << "a:" << a << " b:" << b << endl;
	
	return 0;
}

输出结果为:

交换后 num1= 0000007F4973FAA4 num2= 0000007F4973FA84
a:10 b:20

引用传递

第三个函数接收的参数是一个引用。当我们直接将实参a,b传入函数时,由于形参是一个引用类型,所以就相当于对传入实参做了一个引用,就给实参a,b起了个别名num1,num2,通过交换num1,num2就交换了a,b的数值。看最上面代码输出结果的第四行,a,b数值确实发生了交换。

函数模板参数传递

template<typename T> 
void MySwap(T num1, T num2) {
	cout << "形参交换前 " << "num1: " << num1 << "  num2: " << num2 << endl;
	T temp = num1;
	num1 = num2;
	num2 = temp;
	cout << "形参交换后 " << "num1: " << num1 << "  num2: " << num2 << endl;
}

int main() {
	int a = 10;
	int b = 20;

	//
	cout << "实参交换前变量 " << "a= " << a << " b= " << b << endl;
	MySwap(a, b);
	cout << "实参交换后变量 " << "a= " << a << " b= " << b << endl;
	cout << endl;

	//
	int* aa = &a;
	int* bb = &b;
	cout << "实参交换前指针 " << "aa= " << aa << " bb= " << bb << endl;
	cout << "实参交换前变量 " << "a= " << a << " b= " << b << endl;
	MySwap(aa, bb);
	cout << "实参交换后变量 " << "a= " << a << " b= " << b << endl;
	cout  << "实参交换后指针 " << "aa= " << aa << " bb= " << bb << endl;
	cout << endl;

	//
	int& aaa = a;
	int& bbb = b;
	cout << "实参交换前引用 " << "aaa= " << aaa << " bbb= " << bbb << endl;
	cout << "实参交换前变量 " << "a= " << a << " b= " << b << endl;
	MySwap(aaa, bbb);
	cout << "实参交换后变量 " << "a= " << a << " b= " << b << endl;
	cout << "实参交换后引用 " << "aaa= " << a << " bbb= " << bbb << endl;
}

输出结果为:

//变量作为参数
实参交换前变量 a= 10 b= 20
形参交换前 num1: 10  num2: 20
形参交换后 num1: 20  num2: 10
实参交换后变量 a= 10 b= 20

//指针作为参数
实参交换前指针 aa= 00000072D18FF984 bb= 00000072D18FF9A4
实参交换前变量 a= 10 b= 20
形参交换前 num1: 00000072D18FF984  num2: 00000072D18FF9A4
形参交换后 num1: 00000072D18FF9A4  num2: 00000072D18FF984
实参交换后变量 a= 10 b= 20
实参交换后指针 aa= 00000072D18FF984 bb= 00000072D18FF9A4

//引用作为参数
实参交换前引用 aaa= 10 bbb= 20
实参交换前变量 a= 10 b= 20
形参交换前 num1: 10  num2: 20
形参交换后 num1: 20  num2: 10
实参交换后变量 a= 10 b= 20
实参交换后引用 aaa= 10 bbb= 20

为了代码简洁,上面我们使用了一个函数模板。

值传递

如果我们给函数传递的参数是一个变量,那么不论怎么操作形参,都不会改变实参的值(实参就是传递的变量)。实质上,我们只是把变量的值复制给形参,实参和形参不会共享相同的存储空间,而是各自有各自的内存空间,所以改变形参的值不会改变实参的值。

指针传递

如果我们给函数传递的参数是一个指针,在另一篇博客中我们说了:指针本身数据就是指向的存储空间的地址。地址实质是一个整形,所以模板会自动将地址推导为整形,导致num1,num2就是地址,所以交换num1,num2,就是把地址的数值进行了交换,而不会交换地址内部的数据。

引用传递

由于使用模板进行自动类型推导,我们传入引用,但是引用实质上就是整形变量a,b。模板在进行自动类型推导时,就给推导成了整形变量,所以a,b数值不会发生交换。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

种树家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值