標籤:

什麼時候用指針形參?什麼時候用引用形參?

C/C++語言中,函數傳遞參數的值而不是地址,參數內部對形參的操作不會修改對應的函數外實參的值。如果希望改變實參的值,可以使用指針形參(如 int fun(int *pi))或引用形參(如int fun( int ri ))。那麼,這兩種形參有什麼區別,各有什麼優缺點呢?


就函數參數傳遞而言,傳遞指針與傳遞引用沒有任何優勢,而只是當你有可能需要傳入一個空的概念*(尚未創立的對象,空指針可以表示,而引用無法表示空的概念)的時候,指針才有必要。這應該是指針在函數參數傳遞時的唯一用途了。


如果你想要修改一個參數的值,那麼用指針。

void increase(int * a){ ++(*a);}

int a = 1;
increase(a);

如果你想不修改一個參數的值,那麼用const引用。

std::string concat(const std::string a, const std::string b){
std::string tmp = a+b;
return tmp;
}

std::string a = "hello ";
std::string b = "world."
std::string c = concat(a,b);

單純的引用應該避免使用,因為他在調用的時候不能表示一個參數是否會被函數改變。

void mayBeIncrease(int a){
++a;
}

int a = 10;
mayBeIncrease(a);
// Is a changed?

例如上段代碼中,如果沒有看過mayBeIncrease函數的實現,我們不能確定變數a是否被改變,這就是使用這種非常量引用的問題。而如果只是用指針和常量引用,就能在調用的時候知道變數是否改變了。


C++里有太多微妙到蛋疼的細節。指針和引用的異同也不例外。如果這個問題純粹出於興趣, 可以接著鑽研。

從代碼的可維護性來看,最好能用指針的地方都用指針,避免用引用。因為在使用時引用語法看起來和值語法一樣(有些人可能覺得這樣很酷),不利於理解代碼。

比如原問題中舉例「(如 int fun(int *pi))或引用形參(如int fun( int ri ))」。 在調用fun的地方,開發者馬上能警覺pi所指內容可能在fun中改變,而看不出對ri的影響。

有人可能會說使用const, 那也是在定義的地方,在調用的地方看不見,讀代碼的人總得多看一層。


標準 C 中是沒有引用形參的,只能使用指針形參。

C++ 引入指針形參是為了降低指針靈活性帶來的風險,指針形參不僅可以將數據的引用傳入函數,還可以在函數內改變這個指針,也就是說在函數內部可以改變調用域的變數(而不僅僅是對象)。

相比起引用,指針有這些特點:

  • 指針變數可以被重複賦值或更改(引用則不行,一經賦值不能再改)
  • 指針變數可以為空(引用必須指向具體對象)

如果你用不到這些特性反而覺得它們會帶來麻煩,而且可以接受非 Pure C(例如不需要支持 Objective-C 等其他 C 的超集),那麼就用引用參數吧,甚至還可以在需要的情況下加 const 進一步約束。


一般來說,當你需要調用者確定所傳入的實例對象必須存在的話,就用引用

而對於指針,函數內部使用前需檢驗其是否為空


看個人的愛好風格


指針換shared_ptr或者unique_ptr,傳遞class和struct用引用.除非需要使用虛函數,否則代碼中不出現Type* 定義的變數


推薦閱讀:

c++如何做設計?或者推薦一些比較簡單的開源項目,適合新手練手的。
輪子哥可以分享一下曾經是怎樣帶學生的嗎?
如何評價 Visual C++ 將整合 Clang 用於開發 Windows 程序?
Rust 和 C++ 有哪些優劣?
除了emoji,有沒有用utf16兩個位元組表示不了而且現代文章/姓名中會使用的cjkv字元么?

TAG:C |