C语言函数参数传递的方式可分为3种:值传递,地址传递。(C++中还有引用传递)
通常的建议:
如果传值的话,会生成新的对象,花费时间和空间,而在退出函数的时候,又会销毁该对象,花费时间和空间。
因而如果int,char等固有类型,而是你自己定义的类或结构等,都建议传指针或引用,因为他们不会创建新的对象。
1.值传递:就是把你的变量的值传递给函数的形参,实际就是用变量的值来新生成一个形参,因而在函数里对形参的改变不会影响到函数外的变量的值
void exchg1(int x,int y)
{
int tmp;
tmp=x;
x=y;
y=tmp;
printf("x=%d,y=%d\n",x,y);
}
main()
{
int a=3,b=6;
exchg1(a,b);
printf("a=%d,b=%d\n",a,b);
}
/*其实,函数在调用时,是隐含的把实参a,b的值赋给了形参x,y,之后在函数体内的交换并没有对a,b进行任何操作了,交换的只是x,y变量。这就是所谓的参数的值传递了。*/
2.地址传递:就是传变量的地址赋给函数里形参指针,使指针指向真实的变量的地址,因为对指针所指地址的内容的改变能反映到函数外,也就是能改变函数外的变量的值
void exchg2(int* px,int* py)
{
int tmp = *px;
*px=*py;
*py=tmp;
printf("*px=%d,*py=%d\n",*px,*py);
}
main()
{
int a=3,b=6;
exchg2(&a,&b);
printf("a=%d,b=%d\n",a,b);
}
/*此函数调用的时候也是做了两个隐含的操作,将a,b的地址&a,&b分别带入px,py。经过这样的操作,px,py的值已经分别是a,b变量的地址值了。后面对*px和*py的操作自然是对a,b变量本身的操作了。*/
3.引用传递(C++):实际是通过指针来实现的,能达到使用的效果如传址,可是使用方式如传值。
#include<stdio.h>
void exchg3(int &x, int& y)
{
int tmp = x;
x=y;
y=tmp;
printf("x=%d,y=%d\n",x,y);
}
main()
{
int a=3,b=6;
exchg3(a,b);
printf("a=%d,b=%d\n",a,b);
}
/*参数x,y是int型变量,调用时我们可以想值传递一样调用函数,但是参数前面的&就使得a,b分别代替了x,y,我们称x,y分别引用了a,b变量*/
voidbackward(intn)
{
cout<<n%10;
if(n<10)return;
elsebackward(n/10);
}
intmain()
{
intn;
cout<<"输入整数:"<<endl;
cin>>n;
cout<<"原整数:"<<n<<endl<<"反向数:";
backward(n);
cout<<endl;
return0;
}
函数可以有返回值,只要 return 就可以给出一个。不过我们常常不用它--有两个原因:
1、C/C++里返回值是复制出去的,而对于大的对象,复制的代价很高;
2、有些对象是不能复制的--至少编译器不知道怎么复制--比如数组。
于是我们有了很多这样的函数:
bool GetObj(ObjType& obj);
bool Encode(const char* src, char* dest);
用一个参数来代替返回值,而返回值只是指示函数执行是否成功。我本人一直固执的认为,这是C的处理方式,C++不该这样,返回就是返回,就该光明正大的返回,而不是在文档里为某个参数悄悄注上out。
诚然返回一个大对象是困难的,但这个困难是 C 程序员的,而不是 C++ 程序员的 -- 我们可以返回指针。C也有指针,但很少有人敢在 C 函数里返回一个指针,因为:
1、如果指针指向栈变量,毫无疑问,要么你不用这个返回值,要么是一个错误;
2、如果指针指向堆变量,要么你在祈祷用这个函数的程序员会好好的看文档且足够细心会调用 free, 要么就是内存泄漏;
3、如果指针指向 static 变量,那么用这个函数的程序员牢牢记住“下次调用这个函数以后,上次的返 回值也会跟着变”,要么就是你被别人骂成“专出 BUG 的垃圾”。