本文講解程式語言中指標(Pointer)與參照(Reference)的概念, 並且對比了常見語言中這兩個概念的區別.
指標和參照在C++中是非常重要的概念, 初學者很容易在指標和參照的概念上混淆(因為這兩者太像了).
如何理解兩者的本質:
但在組合層面指標和參照是一樣的,只是編譯器對兩者做了區分,參照可以看作是更加安全的指標,進行了許多限制,大部分情況應該優先使用參照。
下面列個表格,對比這兩者的區別
指標 ( |
參照 ( |
|
---|---|---|
可以多級 (type **a) | √ | × |
可以不用初始化 | √ | × |
可以指向 NULL | √ | × |
可以改變 | √ | × |
有自己獨立的地址 | √ | × |
sizeof(a) | len( |
len( |
自增運算 | 地址++ | 變數值++ |
成員存取 | -> | . |
const(右) | ||
const(左) | const |
const |
使用場景
優先使用參照,必要時用指標
- 指標的操作許可權更多, 容易帶來危險操作
指標的使用場景
參照的使用場景
此外還有函數指標,這裡不談了 (C++的內容實在是繁雜)
Golang中也有指標型別, 但沒有參照.
而且Go的指標也與C++中的指標有很多不同之處:
這裡需要介紹一些關於Go中的函數引數傳遞的知識.
Go中只有值傳遞 (指標型別一樣)
如果需要在函數中修改引數值, 可以使用指標
參照型別變數儲存的是地址, 因此可以在引數中修改原值
Go的變數包括值型別和參照型別, 參照型別只有slice, channel 和 map 三種, 參照型別的特點是變數儲存的是地址, 因此傳參照型別到函數中修改會影響原值.
Python沒有參照, 也沒有顯式的指標, 只有物件參照, 這和其記憶體管理方式密切相關.
Python是通過"參照計數"自動管理記憶體的, 程式中的每個物件的參照個數都會被記錄, 當參照個數為0時會被垃圾回收機制回收, 既不需要分配, 也不用擔心回收.
Python中一切皆物件, 物件是一個三元組 (Id, Type, Value), 變數和物件之間的關係為參照, 變數更像是指標.
Python的物件型別分為可變(mutable)和不可變(immutable). 可變型別包括 list, dict, set, bytearray, user-defined classes, 這些型別在函數內部修改會影響原值.
這裡又會引出淺拷貝和深拷貝的區別. 淺拷貝只複製了物件的參照, 本質共用同一個物件; 深拷貝則是建立了物件的副本, 修改不會影響原值.
Java的資料型別分為基本型別(byte, short, int, long, double, float, char, boolean)和參照型別.
Java中沒有指標, 但參照本質上就是"指標", Java參照儲存實際就是物件的地址, 參照儲存在棧區, 而物件儲存在堆區. 區別在於Java參照對指標進行了封裝, 使其無法直接操作記憶體.
Java參照和C++參照存在區別, Java參照有自己的記憶體 (和C++指標比較像), 儲存地址, 而C++參照只是別名.
C++中,參照和指標的區別是什麼? - 知乎 (zhihu.com)
C++中「參照」的底層實現 - hoodlum1980 - 部落格園 (cnblogs.com)
Go 語言沒有參照型別,指標也與眾不同 - 知乎 (zhihu.com)
Python學習系列之值型別與參照型別_answer3lin的部落格-CSDN部落格
Java真的沒有「指標」嗎? - 知乎 (zhihu.com)