參照
此條目包含過多行話或專業術語,可能需要簡化或提出進一步解釋。 (2012年7月28日) |
此條目沒有列出任何參考或來源。 (2012年7月28日) |
在電腦科學中,參照(英語:reference)是指一個可以讓程式間接存取於電腦記憶體或其他儲存裝置中一特定資料的值,該數據可以為變數或記錄。
參照和資料本身不同。一般而言,參照會是資料儲存於記憶體或儲存裝置中的實體位址。因此,參照亦常被稱為該資料的指標或位址。不過,參照也被用來指資料位址和某一固定「基準」位址的偏移值,或是陣列的索引。
參照的概念和其他如關聯鍵或識別字之類用來識別特定資料項目的值不同,後者只能透過資料庫表中的尋找運算,來存取資料。
參照被廣泛用於程式設計之中,尤其是用於將大量或易變的資料有效地透過參數傳給子程式,或在不同的用途中共享此類資料。此外,參照也能指向一個包含其他資料之參照的變數或記錄,此一概念為間接定址及連結資料結構(如連結串列)之基礎。
例子
編輯指標是最簡單的參照,由於和底層硬體的親密關係,使其成為最強大及有效的參照之一。不過,也因為此一關係,程式設計師在使用指標時,必須非常了解記憶體架構的細節。因為指標儲存記憶體的位址,而非直接儲存值,不正常地使用指標會導致程式出現未定義行為。智慧型指標是一個非透明指標,作用和指標相似,但只能透過特定方式存取。
控制代碼是一種抽象參照,可用許多不同方法呈現。其中一個常見的例子為檔案控制代碼(用於C語言標準輸入/輸出函式庫中的檔案資料結構 ),用來描述抽象的檔案內容。檔案控制代碼通常可用來表示檔案本身(當要求該檔案的鎖時),以及檔案內容中的某一特定位置(當讀存該檔案時)。
在分散式計算中,參照可能包含一個以上的位址或識別字;也可能包括用來定位或存取參照物件之網路協定的編碼格式,用來說明訊息被編碼或序列化之方式。舉例來說,WSDL中對遠端網路服務的描述可被視為一種參照,包括如何定位及綁定特定Web服務之完整格式。另一個例子為對即使分散式物件的參照:該參照為一個如何建設稱之為「代理(proxy)」之小型軟體元件的完整格式,此代理接著會執行點對點(peer-to-peer)的互動,並使本地機器得以存取被複裝或只存在部分一致之訊息串流的資料。
程式語言的支援性
編輯在第一個被使用的程式語言-組合語言中,一般使用未處理的記憶體位址或陣列中的索引表示參照。這樣使用是可行的,但有點微妙,因為一個位址無法告訴你它指向的值是什麼,更不用說這個值有多大,或是該如何解釋;此類訊息都內含在程式的邏輯之中。如此一來,誤解將可能出現在不正確的程式裡,引發令人感到困惑的錯誤。
最早的不透明參照為LISP的CONS函式,此一函式只是一個包含兩個參照至其他Lisp物件的記錄,其他Lisp物件也可能包括其他的cons函式。此一簡單的結構最常被用來建構單向連結串列,但也可用來建構簡單的二元樹,以及一種被稱為「點狀串列」的結構,該結構最終會終止於一個值上,而非空參照。
另一個早期的語言-Fortran則沒有明確用來表示參照的用法,但可以傳參照呼叫的方式使用參照。
指標依然是今日最常見的一種參照,類似於組合語言中對未處理記憶體位址的表示方式,不同之處在於指標帶有一個固定之資料型別,可在編譯期間用來確保所指之資料不被誤解。不過,因為C語言有個可以使用型別轉換(在不同指標型別間及指標型別與整數間轉換)的弱型別系統,雖然較為困難,但還是有可能誤解。C++試圖在C++標準程式庫中使用新的cast運算子及較聰明的指標,以增加型別安全;但為了相容性,仍保留繞過這些安全機制的能力。
許多今日常見的主流語言,如Eiffel、Java、C#及Visual Basic等,則均採用了一種更加不透明的參照,通常即簡稱為「參照」。此類參照具有類似C語言指標的型別,會指出其所參照資料的意思;不過,此類參照為型別安全的,無法指向一個未處理的位址,以及進行不被允許的不安全轉換。
參照與指標的區別
編輯對於同時支援參照與指標的C/C++,兩類資料型的區別有:
- 指標可以重新賦值,而參照在初始化繫結後就不能再繫結到其他對象。
- 指標對象有它自己的主記憶體位址與主記憶體長度,而參照與它指向的對象具有相同的主記憶體位址、主記憶體長度。因此,可以把參照看作是被指向對象的另一個名字。
- 指標可以指向另一指標,因此允許多層的指標間址(indirection);而參照只允許到對象的一層間址,不允許「參照的參照」。
- 指標可以直接賦值為NULL,參照不能。當然,可以費勁辦法把參照繫結到主記憶體的NULL上,但這並不實用。
- 指標可以在陣列上遍歷(iterate),參照不能。
- 指標需要用運算子「*」來解參照(dereference)以訪問它所指向的主記憶體的內容;參照不需要顯式解除參照。指向類/結構的指標訪問成員變數/成員函式需要用運算子->而參照使用運算子.來訪問成員。
- 指標是一個變數,儲存了主記憶體位址;而C++標準都沒有明說參照是如何實現的。實際上,幾乎所有C++編譯器把參照作為一個隱式的指標來實現。
- 指標可以成為陣列的成員類型,即指標陣列;但參照不可以作為陣列的成員類型,即不存在「參照陣列」。
- const參照可以繫結到臨時對象;而指標不能(例如,
int *y = 12;
編譯出錯)。按照C++11語法,const左值參照可以繫結到一切對象,包括const左值對象,非const左值對象,const臨時對象,非const臨時對象;右值參照當然可以繫結到臨時對象。