一.三种传参方式
三种基本的传参方式:值传递,指针传递,引用传递
1. 值传递
首先来看一段代码:
1 void SwapByVal(int a,int b) 2 { 3 int temp = a; 4 a = b; 5 b = temp; 6 } 7 int main() 8 { 9 int a = 5,b = 9; 10 SwapByVal(a, b); 11 std::cout << "a == " << a << " \n" << "b == " << b << "\n"; 12 return 0; 13 }
输出的是 a == 5 b == 9
也就是说,原本是想交换他们的值,但是这里没有交换成功,那么稍微修改下代码:
1 void SwapByVal(int a,int b) 2 { 3 int temp = a; 4 a = b; 5 b = temp; 6 std::cout << "a == " << &a << " \n" << "b == " << &b << "\n"; 7 } 8 int main() 9 { 10 int a = 5,b = 9; 11 std::cout << "a == " << &a << " \n" << "b == " << &b << "\n"; 12 SwapByVal(a, b); 13 std::cout << "a == " << a << " \n" << "b == " << b << "\n"; 14 return 0; 15 }
把主函数中的a和b的地址输出出来,然后再把函数中的a和b的地址输出来
输出结果如下:
这里就可以发现主函数中的a和交换函数中的a的地址不一样,b也是。我们可以把地址想象成一个独立的空间,他们的空间都不一样,一个空间里面的任何东西发生改变,都不会影响另一个空间的东西。又不是平行世界。
那是不是值传递就没有什么用武之处了呢?不是,反而值传递在使用中很频繁的用到。当你只是希望把值传递到另一个函数里面,你只是关心这个值的时候就可以使用这种方法。
2. 指针传递
继续先看一段代码:(为了解释清楚,我这里把形参变一下)
1 void SwapByPointOne(int *p, int *q) 2 { 3 int *temp = p; 4 p = q; 5 q = temp; 6 } 7 void SwapByPointTwo(int *p, int *q) 8 { 9 int temp = *p; 10 *p = *q; 11 *q = temp; 12 }
在main函数中调用:
1 SwapByPointOne(&a, &b); 2 SwapByPointTwo(&a, &b);
为什么会有两种写法呢?输出会不会一样?
先不说输出,先看SwapByPointOne函数,打个形象的例子。我们把内存比作房子,地址比作门牌号,指针比作这个房子外面的标识建筑。a和b在创建的时候就给了他一个门牌号。编辑器是一个邮递员,他只知道a的地址和b的地址是什么,他不关心房子里面住的哪些人,他也是通过地址来发邮件。q和p是个指针,也就是房子外面的标识,一般情况下我们可以通过这个标识来找到他所对应的门牌号,但是,这个标识不是固定的,也许要整改,也许其他原因,他会站到其他门牌号码去。SwapByPointOne就是交换了p和q的位置,但是,邮递员根本不管这个标识,他不熟悉这个地方,也不可能通过标识来派发邮件。那么他只能根据地址来派发邮件。管你标识变不变。所以,这里只是标识变了,但是对于邮递员来说,他只要按照地址去找就不会派发错误的邮件,房子里面的人还是地址上写的那个人。 所以,这里a和b不变。
再来看看SwapByPointTwo这个函数,按照之前的说法,p和q是站在门牌号外面的标识。这里没有交换p和q的位置,却把p和q指向的门牌号对应的房子里的东西都交换了,由于邮递员不关心房子里面到底是什么,所以交换了他也不知道,还是会按照门牌号去派发邮件,结果,里面的人和东西都改变了。所以,这里a和b成功交换。
3.引用传递
同样先看一段代码:
1 void SwapByRef(int &p,int &q) 2 { 3 int temp = p; 4 p = q; 5 q = temp; 6 }
在main函数中调用:
1 SwapByRef(a, b);
根据对指针传递的分析,这里可以形象的理解为SwapByRef 传递的就是a和b的地址,也就是门牌号,而SwapByRef函数本身就是对门牌号对应的房子里面的东西进行交换。那么就可以得出a和b交换成功。
我们在使用指针传递和引用传递的时候应该注意在函数体内对其内存的内容进行修改的时候是会修改实参的内容的,特别是在把一个类的指针对象当作函数的参数传递的时候,更需要很小心处理这个问题。当然,这涉及到之前工作的一个笑话,然后又涉及到类的浅拷贝和深拷贝问题。以后再来说这些问题了。
二. 数组作为函数参数
仍然是先看一段代码:
1 void ChangeByArry(int arry[]) 2 { 3 arry[1] = 2; 4 } 5 void ChangeByArryTwo(int *arry) 6 { 7 arry[1] = 2; 8 } 9 int main() 10 { 11 int a[3] = { 0,1,2 }; 12 ChangeByArryTwo(a); 13 cout << "xxxxxxxxxx== " << a[1] << endl; 14 return 0; 15 }
写简单点,这里有一点要说明,就是数组名在作为形参的时候是要退化成指针的。这点也是面试的时候经常考到的,在函数体内sizeof(arry) 应该为4
差不多就这些,其实还有一个就是把函数名作为参数传递。
难免有误,我只是个想巩固基础的新手0-0 。