哈哈哈,是我,是我,就是我。那咋了。也没咋,就是怪晕头转向的。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的值也就交换了,所以引用传递时形参影响实参。
总结
如果不想修改实参,就用值传递或者形参不修饰实参的地址传递;
如果想修改实参,就用形参修饰实参的地址传递或者引用传递。
但是其实一般大家说地址传递想到的都是形参修饰实参的地址传递,这里就是深化一下啦!
结束!共勉!