2012-07-10 40 views
8

我讀的C++常見問題 - 「8.6 - When should I use references, and when should I use pointers?」,特別是本聲明:C++爲什麼沒有「NULL引用」?

使用引用時,你可以和指針時,你必須。

...

例外上述情況是函數的參數或返回值需要一個「哨兵」參考 - 這並不是指一個對象的引用。這通常最好通過返回/獲取指針來完成,並且賦予NULL指針這種特殊意義(引用必須始終是別名對象,而不是取消引用的空指針)。

從我所看到的,對「標記」引用的需求通常是使用指針而不是引用的原因。我想知道的是:爲什麼C++沒有一個特殊的「NULL值」作爲引用?看起來它會使指針幾乎不必要,這將解決許多問題。

那麼爲什麼它不是語言規範的一部分呢?

編輯:

我不知道我的問題是明確的 - 我想我不litterally詢問NULL引用。大多數情況下,我在C++中讀到「引用是對象」。而且,在大多數OOP語言中,對象可以是NULL - Pascal,C#,Java,JavaScript,PHP等等,你可以使用someObject = nullsomeObject := nil。實際上,Pascal也支持指針,但仍然允許對象爲nil,因爲它有其用處。那麼爲什麼C++在某種程度上是特殊的,並沒有一個NULL對象?這只是一個忽視或一個實際的決定?

+1

祈禱告訴如何將刪除指針的需要? – 2012-07-10 07:54:43

+3

@nathanwhite因爲然後引用將是指針的語法糖,據推測,只要指針是指針就可以使用。國際海事組織將完全刪除參考文件的一些好處。 – hvd 2012-07-10 07:56:46

+4

閱讀[爲​​什麼C++有指針和引用?](http://www2.research.att.com/~bs/bs_faq2.html#pointers-and-references)和[C++:null reference](http:/ /stackoverflow.com/questions/4364536/c-null-reference)。 – 2012-07-10 07:56:48

回答

13

因爲引用帶有語義,它指向一個永不改變的有效內存地址;即解除引用它是安全的/定義的,因此不需要NULL檢查。設計不能重新分配參考。

當var可以爲NULL並且客戶端代碼必須處理該情況時,可以使用指針。您可以保證有效/初始化的內存地址時使用引用。

使用指針的一個例子是作爲一個類的成員來存儲「引用」的某些實例,可能不知道或能夠在類構建時初始化。但是,會員參考必須在施工時初始化(通過初始化名單),並且其分配不得推遲。

如果允許空引用時候,那麼除了語法的指針沒有什麼不同(同一null檢查需要發生。)

更新:

「,並在大多數OOP語言,對象可以是NULL - Pascal,C#,Java,JavaScript,PHP等[...]那麼爲什麼C++在某種程度上是特殊的,並且沒有NULL對象?難道只是一個忽略或實際的決定?「

我覺得你是一個有點困惑這一點。Java和C#等可能會給的印象‘空對象’,但簡單的語法,這些對象的引用都或多或少像C++指針, GC儀器和異常拋出。在這些語言中,如果你在一個「空對象」工作你會得到某種異常的喜歡的NullReferenceException(C#)。地獄,在Java中其稱爲NullPointerException異常

你有檢查null,然後才能安全使用它們。有點像C++ poi (除了在大多數託管語言中,默認情況下指針初始化爲NULL,而在C++中它通常由您負責設置初始指針值(否則未定義/內存已存在))。

C++的觀點是關於有選擇的,因此是詳細:

  • 使用一個普通的指針辦怎麼請你,檢查NULL必要。
  • 使用具有編譯器強制的有效性語義/約束的引用。
  • 滾動你自己的智能指針,做記賬和行爲,無論你想要他們的方式。
  • 如果需要的話,使用void指針(謹慎!)引用一個無類型的內存塊。
+2

Nit:空指針和未初始化的指針是兩個不同的東西。未初始化的指針不能被檢測到,至少不可靠,因爲它可以指向任何地方,包括指向有效的對象。 – hvd 2012-07-10 07:58:11

+0

@ hvd謝謝並修復。通過未初始化我真的意味着NULL。添加了一個關於ctors的部分來說明指針的一個區別使用。 – 2012-07-10 08:03:18

0

引用必須引用某些東西,所以null引用不可用。
C沒有引用,我們只能使用這種語言的指針,所以這是與C語言的兼容性

1

定義引用應該與另一個變量或對象相關聯。所以一個空的或空的引用類型違反了它的存在目的。從技術上講,這意味着你將從一個空引用開始,然後將它分配給某個變量,或者可能被後者重新分配給另一個變量。這根本不是要創建的參考。

還有其他幾個指針的用法,引用可以不復制。如使用指針指向大量複雜數據(一個字節序列)和少量內存,並通過指針消耗大約8個字節來按需要頻繁傳遞該數據。你不能在沒有浪費同等內存的情況下做到這一點。

引用總是綁定到一個類型,而不是指針的情況。

+0

前兩段是正確的。最後一個沒有意義。 – wandalen 2017-02-10 13:02:51

+0

我絕對有一個使用案例,可能或可能沒有在這裏正確闡述。但上面的評論沒有任何闡述,甚至沒有意見,只是「沒有意義」更加無用,沒有任何權重 – fayyazkl 2017-02-10 19:23:18

6

請看看指針和引用之間的區別 - 當標準打開它如何實現引用時,它們目前一直以指針的形式實現。

這意味着它們之間的主要區別是a)語義b)指針可以被重置c)指針可以爲null。

所以簡短的回答是,這是有目的地完成的。當你作爲程序員看到一個引用時,你應該知道a)該引用被填充了b)它不會改變(和c)你可以使用它與對象相同的語義)。

標準是否允許空引用,在使用不需要引用之前,您總是必須檢查null。

編輯:

關於你的編輯,我在這裏想的混亂可能會從事實幹,大多數簡單的面嚮對象語言隱藏到底是怎麼回事。以Java爲例,雖然它看起來像有NULL對象,並且可以分配它們,但實際上不能 - 實際上,Java只有指針,並且可以爲這些指針分配空值。由於不可能直接在Java中實現對象,因此它們會消除指針語義並將指針視爲對象。 C++只是更強大 - 而且容易出錯(Java愛好者會說不需要堆棧用戶類實例,並且決定在Java中不使用它們是爲了降低複雜性,並使Java更易於使用)。此外,由於Java沒有對象,因此它沒有引用。但是,真正沒有幫助的是,Java調用C++人員稱之爲傳遞參數的指針傳遞值。

+0

我已經更新了我的問題。你會如何解釋幾乎所有的OO語言都允許'null'引用,但是C++沒有?在所有這些其他語言中,您並不總是需要檢查NULL,它完全取決於上下文。 – 2012-07-10 08:14:06

+3

我不知道很多面向對象的語言,但對於那些我不同意的語言。 Java甚至沒有引用,Java只有指針(例如可以爲null,可以重新設置),儘管語法不同。 Java沒有引用的原因之一是因爲Java也沒有堆棧變量(缺少內置類型) - 所有東西都是堆,每個變量都是一個指針,因此可以爲空,沒有堆棧內存,不需要引用。 vba也是如此。這與我所知的OO語言數量有關。 – Cookie 2012-07-10 08:19:54

+2

考慮例如一個典型的C++引用用例:你有一些大的堆棧分配變量,並且想通過引用而不是值來傳遞它們。在這裏你需要使用真正的C++引用,並且這樣做是正確的,因爲它們必須是非空的並且不會改變。在Java中,你不能有堆棧變量,所以調用環境總是隻有指針,所以你不需要一個構造來傳遞引用。經常會出現混淆 - Java人稱之爲「通過引用傳遞」,C++人員實際上應該調用「傳遞指針」。 – Cookie 2012-07-10 08:22:59

1

從大多數其他語言使用該術語的意義上來說,C++參考不是一個參考;它更像是一個別名。使用C++引用不會像引用指針一樣引用「取消引用」。它有效地分配給它的對象。

實際上並不存在空對象實例,所以你不能創建一個C++引用這樣的事情。在其他語言中,空引用相當於C++空指針;它實際上並不包含任何內容。

現在,關於你的其他想法:1.有不可空的引用是在我看來,這意味着你通過引用傳遞所有的好處,而不需要檢查整個地方的空值。 2.可爲空的引用不會替換指針......如果您需要在低級別執行內存或IO工作,您將需要原始訪問內存和內存映射設備。正因爲這個原因,您可以看看C#(或C++/CLR),它具有託管引用和非託管指針。

相關問題