【原创】指针和下标的10条对比
?
【原創】指針和下標的10條對比
?
摘要:在編程語言中,指針和下標都是訪問數據的有效手段,本文以C/C++語言為例,講解它們之間的區別。
?
要想完全理解本文,讀者可能需要:
1.至少熟悉一門含有指針和下標語義的編程語言
?
值
指針的值,是一個內存地址,人不容易識別其含義,也很難比較2個指針之間的關系。
下標的值,是一個從小往大的小范圍的整數,人比較容易識別,2個下標之間的關系也一目了然。
?
效率
通過指針訪問數據,一般是一次間址訪問。
通過下標訪問數據,需要先和基地址一起計算得到真實地址,然后再進行訪問,應該會比指針訪問要慢,但差異是微乎其微的,而且還受到編譯器優化的影響,所以2者一般可以認為速度都很快。
?
約束
使用下標,前提是需要知道具體類型的基地址,而使用指針則沒有這個要求。
使用下標還有個隱含的約束,那就是要事先申請到一塊連續的內存空間,而指針則沒有這樣的要求,但我不覺得這個約束是下標的缺點,雖然使用指針比較方便,但由于使用下標必須是存在一塊連續的內存空間,這導致了使用下標會有更好的性能表現。為什么?呵呵,其實這也是只是從概率層面來講的,操作系統里有個概念叫“缺頁”(不知道的請Google),從概率上來講,連續的內存發生缺頁的可能性比離散的內存的發生缺頁的可能性會低很多,一旦發生缺頁,性能就會帶來損失;而且,因為是連續的空間,所以它也容易受益于計算機內部的各種各樣的緩存。遍歷相同規模的數組比遍歷相同規模的鏈表的速度要快(他們的時間復雜度一樣,都是O(n)),便是這一論斷的一個例證。
?
復雜性
這是一個實實在在的使用下標的缺點。當你決定用下標代替指針前,請仔細考量這種改變所帶來的復雜性及增加代碼讀者的理解難度。
?
通用性
支持下標的編程語言比支持指針的編程語言數量要多。
?
判斷合法性
指針,你很難確定一個指針指向的數據是否合法,大部分開發者只是把指針和NULL(nil\空)進行判斷,顯然這無法判斷所有的異常指針。
下標則稍微好點,一般可以知道下標的上下限(C/C++語言 是 0 ~ 數組長度 -1),判斷合法性比較容易。
?
功能
指針能做的,下標一般也能做,比如可以用數組 + 下標 實現一個鏈表,這種鏈表一般被稱為“靜態鏈表”,關于“靜態鏈表”的詳細論述請Google。
?
一致性
同一程序被啟動多次,程序里指針的值可能每次都不一樣,而下標的值應該是一樣的(假設是單線程環境或多線程同步環境)。
2個程序跨機器通信,傳輸指針的值,一般是無用的,因為指針的值是和平臺環境相關,傳輸指針的值,有點像“刻舟求劍”。
2個程序跨機器通信,傳輸下標的值,雖然下標的值跨機器之后仍然是有用的,但考慮到下標本質上是個整數,所以需要考慮字節序的問題,什么是字節序?請Google。
?
可用性
當在表示數組元素時,下標和指針有個很微妙的不同,當數組調用realloc之類的擴展內存的操作后,指針很可能已經失效了,而下標依然是可以使用的。其中很經典的一個例子是用迭代器遍歷STL中的vector,然后在遍歷過程中刪除某些元素。有興趣的讀者可以動手試試。
?
移植性
一個指針本身占用的內存大小一般和CPU/操作系統等環境相關,程序員很難控制。比如sizeof(void *)的大小,在32位計算環境下為4,而在64位計算環境下為8。所以假設一個指針為4個字節,當程序在移植的時候,可能會帶來麻煩。當在64位計算環境下,每個指針的本身的大小是32位環境下的2倍,這會造成計算機內存的額外消耗。其實,我們可以發現,下標是一種簡單有效的指針壓縮技術,基址 + 偏移量(下標)=真實地址,因為下標是數字,所以程序員可以自由選擇8位整數,16位整數,32位整數,64位整數,比較靈活,同時也會減少內存占用。題外話,在Java 6里面,就有針對64位JVM環境下的指針壓縮技術,看來64位指針的內存消耗還是需要引起一定的重視。當然,這也和Java語言的特點有關,因為Java語言里絕大多數的對象都是定義在heap里的,而不像C++,可以自由控制對象定義在stack上還是heap上。對象放在heap里,那么指針就是少不了的,而且一個對象內部可能還包含其他對象的指針,據說64位JVM的內存消耗是32位JVM內存消耗的1.5倍。
?
小結:對不同的事物下一個通用的結論總是很難的,本文也不例外,指針和下標各有優缺點,讀者應該根據使用場景進行合理選擇。
?
轉載于:https://blog.51cto.com/yinghao/625515
總結
以上是生活随笔為你收集整理的【原创】指针和下标的10条对比的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ImageView倒影效果
- 下一篇: 处理局域网网速变慢问题的几个思路