关于函数传参问题(指针传参,值传参,引用传参)
作者:不是杠杠
形参和实参
什么是形参(parameter),什么是实参(argument)
在函数定义中出现的参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据,所以称为形式参数,简称形参。
给形参传递值的变量称为实际参数,简称实参。
形参和实参关系
1) 形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。
2) 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输入等办法使实参获得确定值。
3) 实参和形参在数量上、类型上、顺序上必须严格一致,否则会发生“类型不匹配”的错误。当然,如果能够进行自动类型转换,或者进行了强制类型转换,那么实参类型也可以不同于形参类型。
实参为值传值
代码:
#include<iostream> using namespace std; void swap(int a,int b) { cout<<"a address1 = "<<&a<<endl; cout<<"b address1 = "<<&b<<endl; int temp = a; a = b; b = temp; } int main() { int a = 10; int b = 20; cout<<"a address = "<<&a<<endl; cout<<"b address = "<<&b<<endl; cout<<"original "<<"a = "<<a<<" b="<<b<<endl; swap(a,b); cout<<"swaped "<<"a = "<<a<<" b="<<b<<endl; return 0; }
执行结果:
分析结果:
实参a,b 和形参a,b的地址是不一样的,因为形参a,b是整型变量,他们在函数调用时分配内存,里面只是存放了和实参对应得整型值,所以改变形参变量a,b的值并没有改变实参a,b的值。形参a,b是临时变量,当函数运行结束时,他们的生命周期也就结束了。所以实参a,b的值并没有改变。
图解:
实参为指针传值
实参本身为普通变量
代码:
#include<iostream> using namespace std; void swap(int *a,int *b) { cout<<"parameter a address1 = "<<&a<<endl; cout<<"parameter b address1 = "<<&b<<endl; cout<<"a value address1 = "<<a<<endl; cout<<"b value address1 = "<<b<<endl; int temp = *a; *a = *b; *b = temp; } int main() { int a = 10; int b = 20; cout<<"a address = "<<&a<<endl; cout<<"b address = "<<&b<<endl; cout<<"original "<<"a = "<<a<<" b="<<b<<endl; swap(&a,&b); cout<<"swap "<<"a = "<<a<<" b="<<b<<endl; return 0; }
执行结果:
分析结果:
*p 指的是 指针变量p所指向的地址所存放的内容
&p指的是指针本身的地址
p指的是指针所指向的内容的地址
实参传递的是实参a,b的地址,形参a,b为指针类型的变量,也就是对应存放的是实参a,b变量的地址,函数内交换形参a,b指针所指向地址的内容,也就是交换了实参a,b地址指向空间的内容,所以实参a,b的内容被交换。
图解:
实参本身为指针
一级指针
代码:
#include<iostream> using namespace std; void newPoint(int *p) { cout<<"parameter p address = "<<&p<<endl; p = new int; *p = 10; } int main() { int *p = NULL; cout<<"argument p address = "<<&p<<endl; newPoint(p); cout<<"*p = "<<*p<<endl; delete p; return 0; } ~
执行结果:
分析结果:
实参指针p 没有指向任何类容为空,当实参给形参传递值时,传递的实际上是NULL,形参指针p 分配空间,仅仅只是给形参p分配了空间,当函数退出时,实参指针指向的内容还是为空,这时去访问实参p指向的内容,因为指针没有指向确切地址,就会产生段错误,同时因为函数new了空间没有释放,还会造成内存泄漏。
二级指针
代码:
#include<iostream> using namespace std; void newPoint(int **p) { cout<<"parameter p address = "<<&p<<endl; *p = new int; cout<<"parameter p value = "<<p<<endl; cout<<"parameter *p value = "<<*p<<endl; **p = 10; } int main() { int *p = NULL; cout<<"argument p address = "<<&p<<endl; newPoint(&p); cout<<"argument p value = "<<p<<endl; cout<<"*p = "<<*p<<endl; delete p; return 0; } ~
执行结果:
结果分析:
实参给形参传递的值是实参本身的地址 0x7ffe7feaa980,形参类型是二级指针,形参p存放的是一级指针实参p的地址,调用new之后,相当于是给实参指针p分配了空间,实参指针指向的地址为0x55d013b6d280,给**p赋值,相当于是给地址0x55d013b6d280指向的空间赋值,所以当函数返回时,实参指针指向了确定的地址0x55d013b6d280,并且地址0x55d013b6d280指向的空间值为10;
图解:
引用传值
代码:
#include<iostream> using namespace std; void swap(int& a,int& b) { cout<<"parameter a address = "<< &a<<endl; cout<<"parameter b address = "<< &b<<endl; a = a+b; b = a-b; a = a-b; } int main() { int a = 10; int b = 20; cout<<"argument a address = "<<&a<<endl; cout<<"argument b address = "<<&b<<endl; cout<<"original value"<<"a = "<<a<<" b ="<<b<<endl; swap(a,b); cout<<"swap value"<<"a = "<<a<<" b ="<<b<<endl; return 0; } ~
运行结果:
结果分析:
引用传值,函数形参并没有给形参分配内存,而是和实参相同的内存地址,节省了开销,建议能用引用传值的就用引用。
图解:
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。