給人一種功能時,原來的變量一起工作會是怎樣更好的做法:指針與參考
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
或:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
督察:是否有任何理由要挑一個比另一個?
給人一種功能時,原來的變量一起工作會是怎樣更好的做法:指針與參考
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
或:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
督察:是否有任何理由要挑一個比另一個?
我的經驗法則是:
使用指針,如果你想要做指針運算與他們(例如遞增指針地址步驟通過陣列),或者如果你曾經有傳遞一個NULL指針。
否則使用參考。
有關指針爲NULL的優點。如果你有一個指針參數,那麼你必須明確地檢查它不是NULL,或者搜索函數的所有用法,以確保它不是NULL。引用不需要這種努力。 – 2008-09-22 11:10:02
解釋你的算術意思。一位新用戶可能不瞭解你想調整指針指向的內容。 – 2008-09-22 16:30:29
Martin, 算術我的意思是你傳遞一個指向結構的指針,但知道它不是一個簡單的結構,而是一個數組。在這種情況下,您可以使用[]對其進行索引,或者使用++/- 對指針進行算術運算。 這就是區別。 – 2008-11-25 20:35:40
我真的認爲你會從建立以下函數調用編碼準則受益:
正如其他所有地方,永遠是const
-correct。
const
說明符。如果值0/NULL是當前上下文中的有效輸入,則只能通過指針傳遞值。
理由1:作爲呼叫者,你看,不管你在傳遞必須處於可用狀態。
理由2:由於叫,你知道,無論在來處於可用狀態。因此,不需要對該值進行NULL檢查或錯誤處理。
理由3:理據1和2將是編譯器執行。如果可以的話,一定要在編譯時發現錯誤。
如果函數參數是一個out-value,那麼通過引用傳遞它。
選擇了「以const引用傳遞」僅當值是POD「按值傳遞」(Plain old Datastructure)或者足夠小(以記憶方式)或以其他方式足夠便宜(按時間)複製。
路過常引用,除非有你想改變/保存的內容你傳遞。
這將是在大多數情況下,最有效的方法的原因。
確保您對每個不希望更改的參數使用const,因爲這不僅可以保護您在函數中執行某些愚蠢的操作,還可以向其他用戶顯示該函數對傳入的值的作用。這包括當你只想改變指向什麼的時候指向一個指針...
這最終會變成主觀的。迄今爲止的討論是有用的,但我認爲這沒有一個正確或決定性的答案。很多將取決於時尚的風格指引和您的需求。
雖然使用指針有一些不同的功能(無論是否爲NULL),但輸出參數的最大實際區別純粹是語法。例如,Google的C++風格指南(https://google.github.io/styleguide/cppguide.html#Reference_Arguments)僅規定輸出參數的指針,並且只允許爲常量的引用。理由之一是可讀性:具有價值語法的東西不應具有指針語義含義。我並不是在暗示這一定是對是錯,但我認爲這裏的一點是,這是一個風格問題,而不是正確性問題。
引用是一個隱式指針。基本上你可以改變參考點的值,但是你不能改變參考來指向別的東西。所以我的2美分是,如果你只想改變一個參數的值作爲參考傳遞它,但如果你需要改變參數指向一個不同的對象使用指針傳遞它。
如果您要修改變量的值,您應該傳遞一個指針。 儘管在技術上傳遞引用或指針是相同的,但在用例中傳遞指針更具可讀性,因爲它「通告」了該函數將更改該值的事實。
如果你有一個參數,你可能需要指出缺少一個值,通常的做法是將參數設置爲一個指針值並傳入NULL。
在大多數情況下(從安全角度看),更好的解決方案是使用boost::optional。這使您可以通過引用傳遞可選值,也可以作爲返回值。
// Sample method using optional as input parameter
void PrintOptional(const boost::optional<std::string>& optional_str)
{
if (optional_str)
{
cout << *optional_str << std::endl;
}
else
{
cout << "(no string)" << std::endl;
}
}
// Sample method using optional as return value
boost::optional<int> ReturnOptional(bool return_nothing)
{
if (return_nothing)
{
return boost::optional<int>();
}
return boost::optional<int>(42);
}
考慮C#的out關鍵字。編譯器要求方法的調用者將out關鍵字應用於任何out參數,即使它知道它們是否已經存在。這是爲了提高可讀性。雖然對於現代IDE,我傾向於認爲這是語法(或語義)突出顯示的工作。
如果可以,請使用參考,必要時使用指針。 從C++ FAQ: "When should I use references, and when should I use pointers?"
指針:
nullptr
(或NULL
)。參考文獻:
指針與Vs. Refereces
參考比指針那麼強大:
1)一旦參考被創建,它不能被以後作出引用另一個對象;它不能被重新安裝。這通常是用指針完成的。
2)參考文獻不能爲NULL。指針通常被設置爲NULL來表示它們沒有指向任何有效的東西。
3)聲明時的參考必須初始化。沒有與指針
沒有這樣的限制。由於上述限制,在C++ 引用不能被用於實現像鏈表數據結構,樹等在Java中,引用不具備上述限制,並可用於實現所有數據結構。在Java中引用更強大是Java不需要指針的主要原因。
引用是更安全,更易於使用:
1)更安全:由於引用必須初始化,像野指針野外引用是不可能存在的。它仍然可能有不指更易於使用的有效位置
2)參考文獻:參考文獻不需要對其操作訪問值。它們可以像正常變量一樣使用。 '&'運營商只有在申報時才需要。另外,對象引用的成員可以使用點運算符('。')來訪問,與需要使用箭頭運算符( - >)來訪問成員的指針不同。
連同上述原因,沒有幾個地方像拷貝構造函數的參數,其中不能使用指針。在複製構造函數中必須使用參數傳遞參數。同樣引用必須用於重載一些運營商如++。
引用當然是有價值的,但我來自C,指針無處不在。一個人必須先熟悉指針才能理解引用的價值。 – 2012-05-08 19:43:27
這與函數式編程中的參照透明度等目標是否相符?如果你總是希望函數返回新的對象,並且永遠不會內部改變狀態,尤其是不傳遞給函數的變量。有沒有一種方法,這個概念仍然用於像C++這樣的語言中的指針和引用。 (請注意,我假設有人已經有了參照透明度的目標。我不想談論它是否是一個好目標。) – ely 2013-09-30 17:31:01
喜歡參考。用戶指針,當你沒有選擇。 – Ferruccio 2014-07-05 13:14:21