C++ 函数传参的三种方式(值传递、地址传递、引用传递)

        对于一些基本的数据类型值传递问题不大,但是对于一些复合类型来说,参数中的局部变量会占用空间(虽然调用函数结束空间会自动被回收),对于结构体、类来说会调用构造、析构,可能出现浅拷贝的问题,所以复合类型强烈不建议使用值传递。如果想要在函数内修改外面的实参的值,则使用引用和指针。
值传递:        void mySwapValue(int a, int b)
形参是实参的拷贝, 改变形参的值并不会影响外部实参的值 。从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入,不能传出。
当函数内部需要修改参数,并且不希望这个改变影响调用者时,采用值传递
指针传递(地址传递):        void mySwapPointer(int* a, int* b)

形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。
指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。(这里是在说实参指针本身的地址值不会变

引用传递:        void mySwapReference(int& a, int& b)

形参相当于是实参的“别名”对形参的操作其实就是对实参的操作。在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。
被调函数对形参做的任何操作都影响了主调函数中的实参变量。

函数重载时如何区分值传递和引用传递区分:

1.局部声明化 2.通过指针间接使用

#include<iostream>
using namespace std;

void fun(int a) {
	cout << __FUNCSIG__ << a << endl;
}
void fun(int &a) {
	a = 33;
	cout << __FUNCSIG__ << a << endl;	
}
int main(){
    //局部声明化
	{
		void fun(int& a);
		fun(b);
	}
	
	//函数指针 间接使用
	void(*fun_1)(int) = fun;
	void(*fun_2)(int&) = fun;
	int c = 5;
	fun_1(c);
	fun_2(c);
}

浅拷贝问题:

1.多个对象中的指针指向了同一个申请的空间(new出来的),再回收对象时,同一个空间被释放多次,导致程序异常
2.其中一个对象通过指针修改了指向空间的值,其它对象使用的是修改之后的值

解决方法: 深拷贝  ,需要重构拷贝构造函数,指针指向的空间也需要拷贝一份

总结:

如果想要修改实参的值,不能用值传递,需要使用引用、指针传递,

如果是结构体、类等复合类型,不推荐值传递,因为其额外申请空间的大小是不可控(不可知)

引用传递不额外申请空间,指针传递额外申请的空间大小可控的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值