2010-02-24 36 views
26

可能重複:
Difference between pointer variable and reference variable in C++引用與實現中的指針有什麼不同?

我閱讀的書 「裏面的C++對象模型」,由大師Stanley Lippman。令我百思不解的是對象的「引用」和「指針」的對象之間的差異。我知道一個引用必須在聲明時被初始化,而一個指針可以留給以後的初始化。但我想知道它們之間的物理實現差異。

爲什麼要有「參考」的機制;它不是與指針的功能重疊嗎?在什麼情況下我們應該使用指針以外的參考?非常感謝。

+0

對不起,踩着你的腳趾,hobodave。我同意你的標題更好。 – GManNickG 2010-02-24 02:13:53

+0

可能重複:http://stackoverflow.com/questions/57483/difference-between-pointer-variable-and-reference-variable-in-c – 2010-02-24 02:19:43

+0

感謝,布賴恩和GMAN。 – smwikipedia 2010-02-24 02:31:27

回答

7

大多數參考都是使用指針變量實現的,即參考通常佔用一個字的內存。 然而,優化器可以消除純粹在本地使用的引用,並且經常會這樣做。例如:

struct S { int a, int b[100]; }; 
    void do_something(const vector<S>& v) 
    { 
    for (int i=0; i<v.size(); ++i) { 
     int*& p = v[i].b; 
      for (int j=0; j<100; ++j) cout <<p[j]; 
    } 

在這種情況下,對不需要被存儲在存儲器(可能只是存在於一個寄存器,也許它消失在指令)。

+1

Prasoon,你有一個重複在那裏,我想你需要在你的答案中刪除「are implements」。另外,「它」應改爲「那是」 – legends2k 2010-02-24 02:36:23

+1

@ legends2k:謝謝!完成。 – 2010-02-24 02:37:18

+3

這是有點誤導,因爲本地使用的指針也可以被優化器消除。 – Mehrdad 2015-11-22 09:33:14

1

參考是在大多數情況下在內部指針(存儲或傳遞給函數特別是當)。它們的操作方式與指針的操作方式相同,只要使用對兩者都有效的操作即可。

額外的檢查和語法糖引用是嚴格意義上的編譯時間功能,很像類型系統(有關數據類型的大部分信息在編譯過程中丟失)。

的重要差異是

  • 參考總是指向的對象(不能爲NULL)
  • 的參考點到一個對象只(不象一個指針數組可能)
  • 參考必須是初始化初始化(否則會出現編譯錯誤)
  • 初始化後指向其他地方的引用無法修改
  • 刪除引用指向的對象ce,而參考變量保持活着,是未定義的行爲(但不是編譯錯誤)
+0

+1。將UB展開爲未定義的行爲。 – 2010-02-24 02:20:09

+0

謝謝,Tronic。我從你那裏得知,「參考和類型系統是編譯時功能」。 – smwikipedia 2010-02-24 02:29:28

0

引用對你來說只是一個C++程序員。編譯器無論如何都將引用實現爲指針,所以它不關心你是否使用指針或引用。

正如你所說,引用在許多情況下都比指針更好,因爲它們可以保護被調用方免受不良輸入(壞指針經常導致seg錯誤),並且您也可以將它們設置爲const,這樣可以提供更好的保護,設置一個指向const的指針。

+0

...似乎還是另一種語法糖。謝謝,monoceres。 :D – smwikipedia 2010-02-24 02:30:53

0

C++的引用在很大程度上是一個句法機制。

考慮

int x; 
int &y = x; 
int *z = &x; 

表達式(* z)是一樣的東西(Y)​​。

除了保存你輸入幾個字符之外,這裏唯一的語言事件是,因爲引用不能爲空。

+0

-1並非如此,C++標準並沒有規定如何實現引用(儘管這通常是如何實現的)。此外,你可以破解一個引用,使其顯示爲空,例如「int&y = *(int *)0;」 (但這樣做是非常糟糕的編碼)。 – 2010-02-24 04:09:57

+0

@格蘭彼得斯:我沒有如何實施,我說他們如何有效地工作。 – bmargulies 2010-02-24 12:04:41

+0

是的,我想你沒有。我以前一定讀過太多的東西(可能是因爲讀了這麼多不同的答案),我會收回我的-1,但是似乎並不認爲我們的觀點可能會改變(只有當答案改變時我們才能改變我們的觀點投票) – 2010-02-24 12:32:59

8

的引用可以被認爲是作爲隱含解引用常量指針(注意這一點)。一旦參考,總是一個參考。它允許輕鬆編寫代碼。除非有,否則你會引入移動語義和r值引用。該標準並沒有規定如何實施引用,因爲它沒有規定如何實施指針。大多數情況下,指針與對象的地址是同義的。

5

如果可以,請使用引用,當需要時使用引用。原因你需要使用一個指針:

  1. 有可能不是一個對象爲它指向(空指針,沒有空引用)。
  2. 您可能需要在其生命週期中引用不同的對象。
  3. 您可能需要引用整個對象數組(但std::vector通常更好)。

但是,有一些情況下,兩者的使用並不真正重疊,而且您根本無法替代另一個。對於一個明顯的例子,考慮下面的代碼:

template <class T, size_t N> 
size_t size(T(&matrix)[N]) { 
    return N; 
} 

這可以讓你找到一個數組的大小:

int array1[some_size]; 
int array2[some_other_size]; 

size_t n = size(array1); // retrieves `some_size` 
size_t m = size(array2); // retrieves `some_other_size` 

...但它只是如果你試圖通過將不能編譯它的指針:

int *x = new int[some_size]; 

size_t n = size(x); // won't compile 

在最好的似乎毫無意義的寫代碼來獲得一個指針時,其點的一部分,是拒絕被傳遞的指針。其中

0

一個實例參考應當被用來代替指針:

enum day 
{ 
    Mon, Tue, Wed, Thu, Fri, Sat, Sun 
}; 

day d; 

day *operator++(day *d); 

操作員++可使用++&d,這看起來並不該直觀被調用。這裏的一個大問題是,所有重載的運算符函數必須是類的成員,或者具有類型T的參數,T &或T const &,其中T是類或枚舉類型。所以,在這種情況下, day *operator++(day *d);甚至不會編譯。

它採用基準即

day &operator++(day &d); 

這可以簡單地援引爲++d;

這是從那裏我得到這個例子很好article工作正常。

歡呼聲

+0

你不能重載內置類型的運算符,如指針 – 2010-02-24 04:09:24

+0

那麼,這就是爲什麼它不能被實現。我的答案包括那部分。 – Arnkrishn 2010-02-24 04:32:32

1

指針是一個不同的值,與指向的數據無關。(即使在內存中的地址0x12345678處沒有有意義的數據,數字0x12345678作爲指針值也是有意義的。)因爲它是一個獨特的值,所以它可以獨立操作:可以對其進行遞增或遞減,將其與其他指針進行比較,並將其值顯示在屏幕上,而不管它是否實際上「指向任何東西」。

你不能用一個參考做任何的那些東西,因爲它不是一個獨特的價值。它是一個別名,一個替代名稱(可能在不同的範圍內)用於某些現有值。這使得引用更易於使用(因爲它們的行爲就像它們引用的對象一樣,不需要解引用),並且也更安全(因爲如果使用得當,它們總是引用對象;不存在懸掛或空引用)。

這可能是真實的引用通常會轉換成編譯後的機器代碼的指針,但你應該想到的是,因爲編譯器,不能保證的私人實現細節。引用是他們自己的概念和自己的用例,而不僅僅是指針的不同方式。

當你需要一個不同的類指針值可以操縱和獨立於數據的檢查它指向,使用指針(或,優選地,智能指針類)。當您只需要一種方法來獲取存在於一個範圍內的值並使其在另一個範圍內可用時(例如,將對象傳遞給函數而不復制它),請使用引用。

1

參考是變相的指針,或者至少是把它們的安全方法。

其中一個原因是因爲C和C++沒有「var」參數,就像在Pascal等中一樣。使用引用給出的東西非常接近,但與「var」不同,它也可以在其他地方使用 - 例如給你一個快速的簡寫別的東西......

int& alias = thing.blah [foo]->bar; 
handle (alias, alias+1, alias*2); 

還提及由很多功能恢復,這意味着功能的「結果」可以寫入和讀取,在..

std::deque<int> mydeque; 
mydeque.push_back (1); 
mydeque.back() += 1; // increment the top item on the stack 

使用指針可以實現相同的功能,但引用更方便。通常的術語是「syntactic sugar」。

有關引用的一個有用的(但不是完全可靠的)事實是,你不太可能意外地改變底層指針,因爲它需要多一點的工作訪問的指針,而不是指向的值。這對於選擇有用的提示 - 使用在代碼中創建最少雜亂的提示。

相關問題