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 的垃圾”。