C/C++函数传参详解

问题引出

在编码过程中,新手经常会遇到的一个问题是,我明明在函数中交换了数据,为什么函数外面显示的不对,最常见的例子就是swap()函数。先看两个代码:

代码一:

#include 
void swap(int a, int b)
{
	int t = a;
	a = b;
	b = t;
}
int main()
{
	int a = 3, b = 2;
	swap(a, b);
	printf("%d %d", a, b);
	return 0;
}

代码二:

#include 

void swap(int *a, int *b)
{
	int x = 100;
	int y = 200;
	a = &x;
	b = &y;
}
int main()
{
	int a = 3, b = 2;
	swap(&a, &b);
	printf("%d %d", a, b);
	return 0;
}

这两个代码输出的都是原来的3和2,为什么?特别是第二段代码,明明传进去的是指针,为什么还是不起作用?

代码分析

在函数传参的时候,实际上会发生一次浅拷贝,浅拷贝暂且不表,这里只需要知道,在函数传参的时候,会发生拷贝就可以了。

先看第一段代码,其实际的执行过程为:

(1)声明两个临时变量,int a,int b; (这两个变量跟main中的a和b重名)

(2)让a = a, b = b,=前面的a和b是swap函数声明的临时变量,=后面的是main中的实际变量的值;

(3)int t = a;  //注意这里的a是swap中声明的临时变量,它只是跟main中的变量a有相同的名字,但是他们在内存上的位置是不一样的

(4)a = b; //这里的a和b都是swap声明的临时变量,跟main中的a和b没有任何关系

(5)b=t;//b是swap声明的临时变量,跟main中的b没有任何关系

所以,整个swap函数运行完后,跟main中的a和b实际没有半点关系,有关系的地方仅仅在于(1)中,用main中的a和b的值初始化了swap声明的a和b,仅此而已。所以,这个swap函数对main中a和b的值没有任何影响。

再看第二段代码,其执行过程如下:

(1)声明两个临时变量,int *a,int *b

(2)a=&a,b=&b;=前面的a和b是swap函数声明的临时变量,=后面的是main中的实际变量a和b,也就是把main中a和b的地址分别赋值给swap中的临时变量a和b

(3)a=&x; 把x的地址赋值给a,a的地址发生改变,但a是swap中的临时变量!!!

(4)b=&y; 把y的地址赋值给b,b的地址发生改变,但b是swap中的临时变量!!!

所以,函数运行结束后,函数的功能实际上是改变了两个临时变量a和b的地址,而这两个临时变量跟main函数中变量a和b的关系仅仅是:在声明临时变量a和b的时候,用main中变量a和b的地址初始化了一下,然后再函数体内改变了临时变量a和b的值(内存地址),所以swap中的操作,跟main中的变量a和b没有半点关系,也就不会对他们的值产生影响。

既然上面两种方式都不能达到想要的结果,该怎么办呢?

函数的传参方式

函数传值分为传值和传址两种,传值方式对函数外的变量没有影响,传址方式对函数外的变量有影响,传值和传址的区别不在于参数,而在于在函数体内操作的对象。上面两个代码都属于传值操作,因为再函数体中操作的都是参数值本身。传址方式的差别在于,函数体中操作的是参数指向的内存。

看代码三:

#include 
void func(int* a, int* b)
{
	static int x = 100;
	static int y = 200;
	*a = x;
	*b = y;
}
int main()
{
	int a = 1;
	int b = 2;
	func(&a, &b);
	printf("%d %d", a, b);
	return 0;
}

这段代码跟第二段代码的区别仅仅在于swap函数中的最后两句。

在上面的代码分析中已经知道,函数体中的a是swap的临时变量,a被初始化为了main中变量a的地址,所以\*a =x,这个操作,其本质上就是把x的值放在a指向的内存中,而a指向的内存跟main中变量a的内存是同一块内存,所以,main中变量a的值就会发生改变。同理, \*b=y;将y的值放在了b指向的内存块中,main中b的值会发生改变。这种方式,就是传址。

在C++中,有引用的说法,引用就是变量的一个别名,他们拥有相同的内存,所以代码四也能实现预期的效果。

代码四:


#include 
using namespace std;
//这里的参数是引用,这里的参数a和b,是main中变量a和b的别名,他们具有相同的内存
void swap(int &a, int &b)
{
	int x = 100;
	int y = 200;
	a = x;
	b = y;
}
int main()
{
	int a = 3, b = 2;
	swap(a, b);
	cout << a << " " << b;
	return 0;
}

你可能感兴趣的:(C语言,C++,c语言,c++)