More Effective C++ 條款一 (轉)

gugu99發表於2008-01-25
More Effective C++ 條款一 (轉)[@more@]

條款一:指標與引用的區別

指標與引用看上去完全不同(指標用運算子’*’和’->’,引用使用運算子’.’),但是它們似乎有相同的功能。指標與引用都是讓你間接引用其他。你如何決定在什麼時候使用指標,在什麼時候使用引用呢?

 :namespace prefix = o ns = "urn:schemas--com::office" />

首先,要認識到在任何情況下都不能用指向空值的引用。一個引用必須總是指向某些物件。因此如果你使用一個變數並讓它指向一個物件,但是該變數在某些時候也可能不指向任何物件,這時你應該把變數宣告為指標,因為這樣你可以賦空值給該變數。相反,如果變數肯定指向一個物件,例如你的設計不允許變數為空,這時你就可以把變數宣告為引用。

“但是,請等一下”,你懷疑地問,“這樣的程式碼會產生什麼樣的後果?”

char *pc = 0;  // 設定指標為空值

 

char& rc = *pc;  // 讓引用指向空值

 

這是非常有害的,毫無疑問。結果將是不確定的(能產生一些輸出,導致任何事情都有可能發生),應該躲開寫出這樣程式碼的人除非他們同意改正錯誤。如果你擔心這樣的程式碼會出現在你的裡,那麼你最好完全避免使用引用,要不然就去讓更優秀的員去做。我們以後將忽略一個引用指向空值的可能性。

 

因為引用肯定會指向一個物件,在C裡,引用應被初始化。

string& rs;  // 錯誤,引用必須被初始化

string s("xyzzy");

string& rs = s;  // 正確,rs指向s

 

指標沒有這樣的限制。

string *ps;  // 未初始化的指標

  // 合法但危險

不存在指向空值的引用這個事實意味著使用引用的程式碼比使用指標的要高。因為在使用引用之前不需要測試它的合法性。

void printDouble(const double& rd)

{

  cout << rd;  // 不需要測試rd,它

}  // 肯定指向一個double值

 

相反,指標則應該總是被測試,防止其為空:

void printDouble(const double *pd)

{

  if (pd) {  // 檢查是否為NULL

  cout << *pd;

 }

}

 

指標與引用的另一個重要的不同是指標可以被重新賦值以指向另一個不同的物件。但是引用則總是指向在初始化時被指定的物件,以後不能改變。

 

string s1("Nancy");

string s2("Clancy");

 

string& rs = s1;  // rs 引用 s1

 

string *ps = &s1;  // ps 指向 s1

 

rs = s2;  // rs 仍舊引用s1,

  // 但是 s1的值現在是

  // "Clancy"

 

ps = &s2;  // ps 現在指向 s2;

  // s1 沒有改變

 

總的來說,在以下情況下你應該使用指標,一是你考慮到存在不指向任何物件的可能(在這種情況下,你能夠設定指標為空),二是你需要能夠在不同的時刻指向不同的物件(在這種情況下,你能改變指標的指向)。如果總是指向一個物件並且一旦指向一個物件後就不會改變指向,那麼你應該使用引用。

 

還有一種情況,就是當你過載某個運算子時,你應該使用引用。最普通的例子是運算子[]。這個運算子典型的用法是返回一個目標物件,其能被賦值。

 

vector v(10);  // 建立整形向量(vector),大小為10;

  // 向量是一個在標準C庫中的一個模板(見條款35)

v[5] = 10;  // 這個被賦值的目標物件就是運算子[]返回的值

 

如果運算子[]返回一個指標,那麼後一個語句就得這樣寫:

*v[5] = 10;

 

但是這樣會使得v看上去象是一個向量指標。因此你會選擇讓運算子返回一個引用。(這有一個有趣的例外,參見條款30)

 

當你知道你必須指向一個物件並且不想改變其指向時,或者在過載運算子併為防止不必要的語義誤解時,你不應該使用指標。而在除此之外的其他情況下,則應使用指標。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-998433/,如需轉載,請註明出處,否則將追究法律責任。

相關文章