1、函數的參數傳遞
1.1函數調用的機制
函數的調用過程實際是對棧空間的操作過程(先進後出)。因為調用函數是用棧空間來儲存資訊的。函數調用過程大致描述如下:
1)建立被調用函數的棧空間;
2)儲存調用函數的運行狀態和返回地址;
3)傳遞函數參給形參;
4)執行被調用函數的函數體內語句;
5)將控制權或傳回值交給調用函數。
存放函數的棧區是相互獨立的。函數之間只能通過參數傳遞、傳回值或其他方式進行資料傳遞。
函數在返回時,如果有傳回值,可將它儲存在臨時變數中。然後恢複調用函數的運行狀態。釋放被調用函數的棧空間,按其返回地址返回到調用函數。
(為什麼類傳遞時,構造、析構,特別注意)
#include <iostream>
using namespace std;
void(int a,int b);
void main()
{
int x=5,y=10;
cout<<"x="<<x<<"y="<<y<<endl;
swap(x,y);
cout<<"x="<<x<<"y="<<y<<endl;
}
void swap(int a,int b)
{
int t;
t=a;
a=b;
b=t;
}
1、2函數的傳值調用
swap()和main()的棧區是相互獨立的。在main()中不能訪問swap()中的局部變數a,b,和t.在被調用函數中,改變了形參的值,而不能改變調用函數實參值。這就是C++函數的參數傳值調用的特性。
1.3函數的傳址調用
傳
址調用:是將實參的地址值傳遞給形參,這時形參應是指標,即讓形參指標指向實參地址,這裡不再是將實參拷貝一個副本給形參,而是讓形參直接指向實參。於
是,這就提供了一種可以改變實參變數值的方法:在被調用函數中改變形參所指向的變數值。這便是傳址調用的特點,它與傳值調用的特點。
#include <iostream>
using namespace std;
void(int *a,int *b);
void main()
{
int x=5,y=10;
cout<<"x="<<x<<"y="<<y<<endl;
swap(&x,&y);
cout<<"x="<<x<<"y="<<y<<endl;
}
void swap(int *a,int *b)
{
int t;
t=a;
a=b;
b=t;
}
1、4函數的引用調用
使用引用作函數參數時,要求實參變數名,將實參變數名賦給形參引用,即形參實際上成了實參的別名。引用起到了傳了傳址調用的作用,即不僅可以不傳遞實參的
副本,還可以在被調用函數中參通過形參改變實參值。在引用調用中,實參直接用變數名,形參用引用名,免去使用指標帶來的麻煩。因此,使用引用調用比傳址調
用更為簡單,並且可讀性好。所以,在C++語言中,較多地使用引用調用來替代傳址調用,以簡捷的方式達到了傳址調用的效果。
#include <iostream>
using namespace std;
void(int &a,int &b);
void main()
{
int x=5,y=10;
cout<<"x="<<x<<"y="<<y<<endl;
swap(x,y);
cout<<"x="<<x<<"y="<<y<<endl;
}
void swap(int &a,int &b)
{
int t;
t=a;
a=b;
b=t;
}
2、函數的傳回值
2.1值返回
在帶有傳回值的函數中,需要使用return語句返回一個運算式的值,如:return 運算式;一般函數傳回值時都要建立臨時變數,即用來拷貝副本。
2、2引用返回
引用傳回值時,不產生值的副本,而是將其傳回值直接傳遞給接收函數傳回值的變數或對象。
#include <iostream>
using namespace std;
class INCREASE
{
public:
INCREASE (int x=0):value(x){}
INCREASE &operator++(int);
void display();
private:
int value;
};
INCREASE &INCREASE::operator++(int)
{
value++;
return *this;
}
void INCREASE::display()
{
cout<<value<<endl;
return;
}
void main()
{
INCREASE a(100),b;
b=a++;
b.display();
}
對象引用調用
#include <iostream>
using namespace std;
class Animal
{
public:
Animal(){cout<<"Animal./n";}
void eat(){cout<<"eat./n";}
virtual void take(){eat();}
~Animal(){cout<<"delAnimal./n";}
};
class Giraffe:public Animal
{
public:
Giraffe(){cout<<"Giraffe./n";}
void StretchNeck(){ cout<<"stretch neck,/n";}
virtual void take(){eat();}
~Giraffe(){cout<<"delGiraffe./n";}
};
void Func(Animal &an)
{
an.take();
}
void main()
{
Giraffe gir;
gir.StretchNeck();
Func(gir);
gir.StretchNeck();
}