Bootstrap

都2025年了,不会还有人搞迷糊值传递、地址传递和引用传递吧?!本篇文章就带你理清这三者的区别与使用!

哈哈哈,是我,是我,就是我。那咋了。也没咋,就是怪晕头转向的。So,go studying!拿下!!!

1. 值传递

所谓值传递,就是函数调用时实参将变量的值传给形参;

值传递时,如果形参发生改变,并不会影响实参;

示例代码:

void swap(int m,int n) 
{
	cout << "before swap start: " << endl;
	cout << "m的值等于 " << m << "\tm的地址为 " << &m << endl;
	cout << "n的值等于 " << n << "\tn的地址为 " << &n << endl;
	cout << endl;

	int temp = m;
	m = n;
	n = temp;

	cout << "after swap over: " << endl;
	cout << "m的值等于 " << m << "\tm的地址为 " << &m << endl;
	cout << "n的值等于 " << n << "\tn的地址为 " << &n << endl;
	cout << endl;
}

int main() 
{

	int a, b;

	a = 10;
	b = 20;

	cout << "before swap: " << endl;
	cout << "a的值等于 " << a << "\ta的地址为 " << &a << endl;
	cout << "b的值等于 " << b << "\tb的地址为 " << &b << endl;
	cout << endl;

	swap(a, b);

	cout << "after swap: " << endl;
	cout << "a的值等于 " << a << "\ta的地址为 " << &a << endl;
	cout << "b的值等于 " << b << "\tb的地址为 " << &b << endl;
	
	system("pause");

	return 0;
}

当箭头指向(下一步将执行swap函数,进入):

此时监视窗口:

当箭头指向(下一步将正式开始交换):

此时监视窗口:

当箭头指向(swap函数执行完成,出来):

此时监视窗口:

从监视窗口可以看到,值传递时,a、b和m、n指向四块不同内存,我们进行swap,实际是将m、n这两块内存上存储的值进行交换(m、n的地址始终未变即还是这两块内存),也就是相当于重新对m、n这两块内存存储的数据进行赋值,而并不影响a、b,即a、b的地址和值都不会有任何改变。

2. 地址传递

地址传递有两种可能:形参修饰实参,形参不修饰实参。下面我将分别介绍。


【形参修饰实参】

示例代码:


void swap01(int *m,int *n) 
{
	cout << "before swap start: " << endl;
	cout << "m的值等于 " << *m << "\tm的地址为 " << &m << endl;
	cout << "n的值等于 " << *n << "\tn的地址为 " << &n << endl;
	cout << endl;

	int temp = *m;
	*m = *n;
	*n = temp;

	cout << "after swap over: " << endl;
	cout << "m的值等于 " << *m << "\tm的地址为 " << &m << endl;
	cout << "n的值等于 " << *n << "\tn的地址为 " << &n << endl;
	cout << endl;
}

int main() 
{

	int a, b, * p1, * p2;

	a = 10;
	b = 20;

	cout << "before swap: " << endl;
	cout << "a的值等于 " << a << "\ta的地址为 " << &a << endl;
	cout << "b的值等于 " << b << "\tb的地址为 " << &b << endl;
	cout << endl;

	p1 = &a;
	p2 = &b;

	//swap(a, b);
	swap01(p1, p2);

	cout << "after swap: " << endl;
	cout << "a的值等于 " << a << "\ta的地址为 " << &a << endl;
	cout << "b的值等于 " << b << "\tb的地址为 " << &b << endl;
	
	system("pause");

	return 0;
}

当箭头指向(下一步将执行swap01函数,进入):

此时监视窗口(p1和&a是一个意思,p1=&a):

当箭头指向(下一步将正式开始交换):

此时监视窗口(m是一个指针,p1的值传给了m,m=p1=&a,可以理解m和p1都指向变量a):

当箭头指向(swap01函数执行完成,出来):

此时监视窗口:

从监视窗口可以看到,在形参修饰实参的地址传递时,m和n所指向的两块内存的值发生了交换,而m=p1=&a,n=p2=&b,即实参a和b这两块内存的值发生了交换,所以形参影响了实参。


形参不修饰实参

示例代码:

void swap02(int *m, int *n) 
{
	cout << "before swap start: " << endl;
	cout << "m的值等于 " << *m << "\tm的地址为 " << &m << endl;
	cout << "n的值等于 " << *n << "\tn的地址为 " << &n << endl;
	cout << endl;

	int *temp = m;
	m = n;
	n = temp;

	cout << "after swap over: " << endl;
	cout << "m的值等于 " << *m << "\tm的地址为 " << &m << endl;
	cout << "n的值等于 " << *n << "\tn的地址为 " << &n << endl;
	cout << endl;

}

int main() 
{

	int a, b, * p1, * p2;

	a = 10;
	b = 20;

	cout << "before swap: " << endl;
	cout << "a的值等于 " << a << "\ta的地址为 " << &a << endl;
	cout << "b的值等于 " << b << "\tb的地址为 " << &b << endl;
	cout << endl;

	p1 = &a;
	p2 = &b;

	//swap(a, b);
	//swap01(p1, p2);
	swap02(p1, p2);

	cout << "after swap: " << endl;
	cout << "a的值等于 " << a << "\ta的地址为 " << &a << endl;
	cout << "b的值等于 " << b << "\tb的地址为 " << &b << endl;
	
	system("pause");

	return 0;
}

当箭头指向(下一步将执行swap01函数,进入):

此时监视窗口(p1和&a是一个意思,p1=&a):

当箭头指向(下一步将正式开始交换):

此时监视窗口(m是一个指针,p1的值传给了m,m=p1=&a,可以理解m和p1都指向变量a):

当箭头指向(swap01函数执行完成,出来):

此时监视窗口:

从监视窗口可以看到,在形参不修饰实参的地址传递时,是将指针m和n的指向进行了交换,即原来m指向a,n指向b,交换后,m指向b,n指向a,而a和b这块内存上存储的值并未变化,所以说形参不影响实参。


也不知道大家看迷糊了没有?哈哈哈,我也好迷糊,可以在纸上画画示意图,帮助理解。

3. 引用传递

首先,知道引用的概念:

引用,是给同一块内存起别名,别名和原名都可以修改同一内存中的数据。

注意区分:赋值,是重新开辟一个内存将原名数据赋值给新名,是两块内存。

示例代码:

int main() 
{
	int a = 10;
	int& c = a;//这是引用
	int d = a;//这是赋值

	cout << "a的值等于 " << a << "\ta的地址为 " << &a << endl;
	cout << "c的值等于 " << c << "\tb的地址为 " << &c << endl;
	cout << "d的值等于 " << d << "\tb的地址为 " << &d << endl;
	
	system("pause");

	return 0;
}

执行结果:


下面进入正题,对于引用传递,形参也会修饰实参:

示例代码:

void swap(int &m, int &n)
{
	cout << "before swap start: " << endl;
	cout << "m的值等于 " << m << "\tm的地址为 " << &m << endl;
	cout << "n的值等于 " << n << "\tn的地址为 " << &n << endl;
	cout << endl;

	int temp = m;
	m = n;
	n = temp;

	cout << "after swap over: " << endl;
	cout << "m的值等于 " << m << "\tm的地址为 " << &m << endl;
	cout << "n的值等于 " << n << "\tn的地址为 " << &n << endl;
	cout << endl;
}


int main() 
{
	int a, b;

	a = 10;
	b = 20;

	cout << "before swap: " << endl;
	cout << "a的值等于 " << a << "\ta的地址为 " << &a << endl;
	cout << "b的值等于 " << b << "\tb的地址为 " << &b << endl;
	cout << endl;

	swap(a, b);

	cout << "after swap: " << endl;
	cout << "a的值等于 " << a << "\ta的地址为 " << &a << endl;
	cout << "b的值等于 " << b << "\tb的地址为 " << &b << endl;
	
	system("pause");

	return 0;
}

当箭头指向(下一步将执行swap函数,进入):

此时监视窗口:

当箭头指向(下一步将正式开始交换):

此时监视窗口:

当箭头指向(swap函数执行完成,出来):

此时监视窗口:

从监视窗口可以看到,在引用传递时,m和a指向同一块内存,n和b指向同一块内存,m和n交换就是对这两块内存的值进行交换,自然a和b的值也就交换了,所以引用传递时形参影响实参。

总结

如果不想修改实参,就用值传递或者形参不修饰实参的地址传递;

如果想修改实参,就用形参修饰实参的地址传递或者引用传递。

但是其实一般大家说地址传递想到的都是形参修饰实参的地址传递,这里就是深化一下啦!

结束!共勉!

;