C++學習隨筆之五:C++函數的新特點

來源:互聯網
上載者:User

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 …… 個都應該是預設參數,所以預設參數應該放在參數列表的最“後”面。也即是說,如果要為某個參數設定為預設值,則必須為後面的所有參數提供預設值。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.