一、概述
C/C++中存在三种函数参数传递方式,值传递、引用传递、指针传递。
函数参数传递方式 | 其他称呼 | 实参 | 形参 | 本质 |
值传递 | 传值 | 普通变量 | 普通变量 | 普通变量传递数值 |
引用传递 | 传引用 | 普通变量 | 引用变量 | 普通变量传递引用 |
指针传递、地址传递 | 传地址(传址) | 引用变量 | 指针变量 | 指针变量传递地址 |
有不清楚普通变量、引用变量、指针变量的,转至:我说C/C++——普通变量、引用变量、指针变量
注意:C语言中支持两种参数传递方式——值传递和指针传递,C++中支持三种传递方式——值传递、引用传递和指针传递,对于引用传递,C语言不支持,但是C++支持。本节演示的程序时C++程序,因为C语言中引用传递演示不出来。
二、代码
2.1 值传递(传值)
代码1:
#include<iostream>
using namespace std;
//值传递 交换前a=1,b=2;交换后a=1,b=2;
void swapByValue(int a,int b)
{
cout<<"swapByValue函数 交换前"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
int temp=a;
a=b;
b=temp;
cout<<"swapByValue函数 交换后"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
}
//主函数
int main()
{
int a=1;
int b=2;
cout<<"main函数 交换前"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
swapByValue(a,b);//值传递
cout<<"main函数 交换后"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
return 0;
}
输出1:
小结1:可以看出main函数中a、b变量的内存地址和swap函数中a、b变量的内存地址没有任何关系。
因为它们本来就是两套独立的存储位置,相互之间没有任何关系,从main函数中调用swapByValue函数,是指将a、b参数的值传递过去,所以内存地址为0xfafed0、0x6afed4的a、b变量的值的变化不会影响到内存地址0xfafeec、0x6afee8的a、b变量的值。
如果一定要影响main中a、b变量的值,只能使用return返回,不过,可惜的是,return只能返回一个变量值(返回结构体或自定义类另说)。
2.2 引用传递(传引用)
代码2:
#include<iostream>
using namespace std;
//引用传递 交换前a=1,b=2;交换后a=2,b=1;
void swapByReference(int &a,int &b)
{
cout<<"swapByReference函数 交换前"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
int temp=a;
a=b;
b=temp;
cout<<"swapByReference函数 交换后"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
}
//主函数
int main()
{
int a=1;
int b=2;
cout<<"main函数 交换前"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
swapByReference(a,b);//引用传递
cout<<"main函数 交换后"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
return 0;
}
输出2:
小结2:main函数将a、b变量的引用(别名)传递给swapByReference函数,则swapByReference函数中a、b变量仅仅是main函数中a、b变量的引用(别名),不是一个新的真是存在的变量,所以swapByReference函数中的a变量的地址也是0x6afeec,和main函数中a变量的地址一样,swapByReference函数中的b变量的地址也是0x6afee8,和main函数中b变量的地址一样。
swapByReference函数中,交换了两个内存地址上的内容,因为swapByReference函数中的a、b变量作用域今夏与swapByReference函数,所以随着swapByReference执行完毕,其中的a、b变量也没什么用了。
再次回到main函数,main函数的a、b变量存放于0x6afeec地址和0x6afee8地址中,然后将它们输出交换结果即可。
2.3 指针传递、地址传递(传地址(传址))
因为指针变量的内容就是十六进制的内存地址,所以指针传递就是地址传递,又称为传地址。
代:3:
#include<iostream>
using namespace std;
//指针传递 交换前a=1,b=2;交换后a=2,b=1;
void swapByAddress(int *a,int *b)
{
cout<<"swapByAddress函数 交换前"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" *a="<<*a;
cout<<" *b="<<*b<<endl;
int temp=*a; //注意:a是地址 *a是内容 b是地址 *b是内容 这里是内容交换,所以是*a和*b交换 这种写法正确
*a=*b;
*b=temp;
cout<<"swapByAddress函数 交换后"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" *a="<<*a;
cout<<" *b="<<*b<<endl;
// int temp=a; //注意:a是地址 *a是内容 b是地址 *b是内容 这里是内容交换,所以是*a和*b交换
// a=b; //这种写法正确 这样交换的是地址
// b=temp;
}
//主函数
int main()
{
int a=1;
int b=2;
cout<<"main函数 交换前"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
swapByAddress(&a,&b);//指针传递
cout<<"main函数 交换后"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
return 0;
}
输出3:
小结3:和上面引用传递不同,在swapByAddress函数中,参数a、b为int *类型(整型指针类型),所以swapByAddress函数中,a、b表示的是地址,*a *b表示的是内容。
从结果中可以看到,实参为&a,&b将变量地址传递给swapByAddress函数,函数接收到地址,使用*a *b获取地址上的内容,交换地址上的内容,最后在main函数中输出。
指针传递中,记住一种错误示范:
代码:
#include<iostream>
using namespace std;
void errorFun(int *a,int *b) //错误示范
{
cout<<"swapByAddress函数 交换前"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" *a="<<*a;
cout<<" *b="<<*b<<endl;
int *temp=a; //注意:a是地址 *a是内容 b是地址 *b是内容 这里是内容交换,所以是*a和*b交换 这种写法正确
a=b;
b=temp;
cout<<"swapByAddress函数 交换后"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" *a="<<*a;
cout<<" *b="<<*b<<endl;
// int temp=a; //注意:a是地址 *a是内容 b是地址 *b是内容 这里是内容交换,所以是*a和*b交换
// a=b; //这种写法正确 这样交换的是地址
// b=temp;
}
//主函数
int main()
{
int a=1;
int b=2;
cout<<"main函数 交换前"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
errorFun(&a,&b);//指针传递
cout<<"main函数 交换后"<<endl;
cout<<"a="<<a;
cout<<" b="<<b;
cout<<" &a="<<&a;
cout<<" &b="<<&b<<endl;
return 0;
}
输出:
注意:这是一种错误的示范,swapByAddress函数中交换的是int *a,int * b的十六进制的地址,而不是内存地址中的内容,这种地址交换效果类似于值交换,地址交换的结果是不会影响到调用方main函数的,所以main函数中还是a=1,b=2.
三、小结
本节介绍C/C++函数参数传递的三种方式——传值、传引用、传地址。
天天打码,天天进步!
附:引用传递和指针传递的区别
注意:C语言中支持两种参数传递方式——值传递和指针传递,C++中支持三种传递方式——值传递、引用传递和指针传递,对于引用传递,C语言不支持,但是C++支持,所以上面的程序可以编译通过。
值传递和指针传递的区别是明显的,值传递是普通变量传递数值,指针传递是指针变量传递引用。
这里谈论引用传递和指针传递的区别,根本区别:引用传递中形参和实参是同一对象,指针传递中形参和实参指向同一对象。
相同点 | 根本区别 | 结合上面的程序解释 | 实参 | 形参 | |
引用传递 | 第一,引用变量存储的是变量的地址,指针变量存储的也是变量的地址,都是十六进制的内存地址 第二,形参地址和实参地址一样,都不需要为形参开辟新的内存地址 |
形参和实参是同一对象 | 实参为int型变量,形参是int型引用变量,形参是实参的引用(即别名),因为形参仅仅是实参的别名,所以形参和实参是同一内存地址的对象 | 普通变量 | 引用变量 |
指针传递(即地址传递) | 形参和实参指向同一对象 | 实参是int变量的地址,形参是指针变量,指针变量存放的还是地址,将实参的地址传递给形参,形参和实参指向的是同一地址,同一对象 | 引用变量 | 指针变量 |
有不清楚普通变量、引用变量、指针变量的,转至:我说C/C++——普通变量、引用变量、指针变量