1.內嵌函式:是以空間(記憶體空間)代價換取時間的(程式執行效率),不能使用遞迴。既可以用於值傳遞,也可以用於地址傳遞,而宏不能用於
值傳遞。內嵌函式一般在如下情況下採用:程式中多次調用,而且函數代碼執行時間較短時採用。
2.引用(變數):主要用途是用作函數的形參。
3.引用與指標的區別:
(1)引用必須在其聲明時就初始化,即必須在建立時就將它初始化,而不像指標那樣,可以先聲明,後初始化
#include<iostream>
using namespace std;
int main()
{
int rat = 100;
int & shu = rat;
cout << "rat = " << rat;
cout << ", " << "shu = " << shu << endl;
cout << "rat address: " << &rat ;
cout <<", " << "shu address: " << &shu <<endl;
int cat = 50;
shu = cat;
cout << "cat = " << cat;
cout <<", " << "rat = " << cat ;
cout <<", " << "shu = " << shu <<endl;
cout <<"cat address: " << &cat;
cout <<", " << "shu address: " << &shu <<endl;
cin.get();
return 0;
}
運行上面程式結果如下:
上面結果,顯示了,rat的值也變成了50,同時,rat與shu地址相同,而該地址與cat地址不同。因為shu是rat的別名,所以shu=cat語句的與下面語 句等效:rat = cat;也意味著將cat變數的值賦給rat變數。通過上面例子,總之,可以通過初始化聲明來設定引用,而但不能通過賦值來設定引用,否則
會出現意想不到的嚴重的後果。
4.引用的一個作用就是用作形參,但注意:用引用做參數時(形參),它很有可能習慣調用函數的值,即實參的值。
臨時變數、引用參數和const:
如果實參與引用參數不匹配,則C++將產生臨時變數,現在,僅當參數為const引用時,C++才允許這樣做的。
如果引用參數為const,則在以下兩種情況會產生臨時變數:
a.實參的類型不正確,但不是左值。
b.實參的類型不正確,但可以轉換為正確的類型。
左值參數是可被引用的對象,例如,變數,數組元素,結構成員,引用或被解除引用的指標都是左值。
非左值包括字面常量和包含多項的運算式。
樣本:
double refcube(const double & ra)
{
return a*a*a;
}
double side =3.0;
double *pd = &side;
double & rd=side;
long edge = 5L;
double lens[4] = {1.0,2.0,3.0,4.0};
double c1= refcube(side) ; //ra is side;
double c2=refcube(lens[2]); //ra is lens[2]
double c3= refcube(rd); //ra is rd is side
double c4 = refcube(*pd); //ra is *pd is side
double c5 = refcube(edge); //ra is temporary variable
double c6 =refcube(7.0); //ra is temporary variable
double c7 = refcube(side + 10.0); // ra is tempoary variable
參數side、lens[2]、rd和*pd 都是有名稱的、double資料類型的對象,因此可以為其建立引用,而不需要臨時變數。但是,edge雖然是變數,類型
卻不正確,double引用不能指向long,還有,參數7.0和side+10.0雖然類型正確,但沒有名稱,在這種情況下,編譯器將產生一個臨時匿名變數,
並讓ra指向它。這些臨時變數只在函數調用期間存在,此後編譯器便可以隨便將其刪除。
在沒有特殊情況下,一般講形參引用設為const,應儘可能使用cosnt,原因有如下三點:
(1)使用const可以避免無意中修改資料的編程錯誤。
(2)使用const使函數能夠處理const和非const實參,否則將只能接受非const資料
(3)使用cosnt引用使函數能夠正確產生並使用臨時變數
5.引用的第二個作用:用於結構。
#include<iostream>
using namespace std;
struct sysop
{
char name[26];
char quote[64];
int used;
};
const sysop & use(sysop & sysopref)
{
cout << sysopref.name <<"says: " << endl;
cout << sysopref.quote <<endl;
sysopref.used ++;
return sysopref;
}
int main()
{
sysop looper =
{
"caizhiming",
"寶劍鋒從磨礪出,梅花香自苦寒來",
0
};
use(looper);
cout <<"Looper: "<<czm.used << " use(s)" <<endl;
sysop copycat;
copycat = use(looper);
cout <<"Looper: "<<looper.used << " use(s)" <<endl;
cout <<"Copycat: "<<copycat.used << " use(s)" <<endl;
cout <<"use(looper): "<<use(looper).used << " use(s)" <<endl;
cin.get();
return 0;
}
在上面程式碼中,將引用作為傳回值。通常,返回機制將傳回值複製到臨時儲存地區中,隨後調用程式將訪問該地區,然後,返回引用意味著調用程式將直接存取傳回值,而不需要拷貝。通常,引用將指向傳遞函數的引用,因此調用函數實際上是直接存取自己的一個變數。例如上面例子中,sysopref是looper的引用,因此傳回值是main函數中的原始looper變數。
返回引用時應注意:避免返回當函數終止時不再存在的記憶體單元引用,同樣使用指標時也應避免返回指向臨時變數的指標!
6.引用的第三個個作用:用於類對象
將類對象傳遞給函數時,C++通常的做法就是使用引用。例如,可以通過引用,讓函數將類string、ostream、istream、ofstream和ifstream等類的對象作為參數。如果一個類是從另一個類派生出來的,則基類的引用可以指向衍生類別的對象。
7.對於什麼時候使用引用,什麼時候使用指標,什麼時候應按值傳遞,一般遵循以下原則:
(1)對於使用傳遞的值而不作修改的函數:
a.如果資料對象很小,如內建資料類型或小型結構,則按值傳遞。
b.如果資料對象是數組,則使用指標,因為這是唯一的選擇,並且將指標聲明為指向const的指標。
c.如果資料對象是較大的結構,則使用const指標或const引用,以提高程式的效率。這樣可以節省複製結構的空間和時間。
d.如果資料對象是類對象,則使用const引用。類設計的語義常常要求使用引用,這是C++新增引用的主要原因,因此,傳遞類對象參數的標準方式是
按引用傳遞。
(2)對於修改調用函數中資料的函數:
a.如果資料對象是內建資料類型,則使用指標。如果看到fixit(&x)這樣的代碼(其中x是int類型),改函數將修改x。
b.如果資料對象是數組,則使用指標。
c.如果資料對象是結構,則使用引用或指標。
d.如果資料對象是類對象,則使用引用。
引用的引入只要適用於結構和類對象的。
8.函數重載:函數重載的關鍵是參數列表——也稱為函數特徵標。函數重載必須是特徵標不同,傳回型別可以不相同。函數名相同,只需要特徵標(參數列表)不同,就是函數多態(或函數重載)。函數模板自動完成重載函數的過程。
9.函數模板:這裡要注意的是 template<class T> 不是一個獨立的語句,它必須和方法定義聲明或類聲明是一體的,雖然有時分兩行來寫。
程式碼範例:
#include<iostream>
using namespace std;
template<class T>
void Swap(T &a,T &b);
template <class T>
void Swap(T &a,T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int i=10;
int j=20;
cout << i << "," << j <<endl;
Swap(i,j);
cout << i << "," << j <<endl;
double m = 12.34;
double n =20.57;
cout << m << "," << n <<endl;
Swap(m,n);
cout << m << "," << n <<endl;
cin.get();
return 0;
}
10.預設參數:
如果第N個參數預設的話,第N+1 N+2 …… 個都應該是預設參數,所以預設參數應該放在參數列表的最“後”面。也即是說,如果要為某個參數設定為預設值,則必須為後面的所有參數提供預設值。