Java中的引用和C++中引用的區別

用過java和C++的同窗都知道在兩者中均有引用的概念。可是這兩個概念所表明的並不相同。 java

首先了解C++ 中引用的含義:「引用」即「別名」。C++中的引用表明的就是實際的存儲空間。對其進行操做就是對存儲空間進行操做。 數組

而在Java中的引用:能夠看作是C語言中的「指針」或者「地址」。對java中引用的屬性(即指針指向的存儲空間)進行操做纔是有效的。 數據結構

參考http://blog.csdn.net/wzy_1988/article/details/16886337函數

測試

java內存分配中的棧

在函數中定義的一些基本類型的變量數據和對象的引用變量都在函數的棧內存中分配

當在一段代碼塊定義一個變量時,java就在棧中爲這個變量分配內存空間,當該變量退出該做用域後,java會自動釋放掉爲該變量所分配的內存空間,該內存空間能夠當即被另做他用


java內存分配的堆

堆內存用來存放由new建立的對象和數組。在堆中分配的內存,由java虛擬機的自動垃圾回收器來管理

在堆中產生了一個對象或數組後,還能夠在棧中定義一個特殊的變量,讓棧中這個變量的取值等於數組或對象在堆內存中的首地址,棧中的這個變量就成了數組或對象的引用變量。引用變量就相等因而爲數組或對象起的一個名稱,之後就能夠在程序中使用棧中的引用變量來訪問堆中的數組或對象。引用變量就至關因而爲數組或者對象起的一個名稱

引用變量是普通的變量,定義時在棧中分配,引用變量在程序運行到其做用域以外後被釋放。而數組和對象自己在堆中分配,即便程序運行到使用new產生數組或對象的語句所在的代碼塊以外,數組和對象自己佔據的內存不會釋放,數組和對象在沒有引用變量指向它的時候,才變爲垃圾,不能在使用,但仍然佔據內存空間不不放,在隨後的一個不肯定的時間垃圾回收器收走(釋放掉)。這也是java比較佔內存的緣由

實際上,棧中的變量指向堆內存中的變量,這就是java中的指針!


對於概念有所瞭解了以後,主要來看看咱們常常容易困惑的地方——引用傳參: spa

1)Java引用做爲函數(方法)參數 .net

Java的方法參數只是傳值,引用做爲參數使用時,會給函數內引用的值的COPY,因此在函數內交換兩個引用參數是沒有意義的,由於函數交換的是參數的COPY值;可是在函數內改變一個引用參數的屬性是有意義的,由於引用參數的COPY值指向的對象和原引用指向的是同一個對象。 指針

2)C++引用做爲函數參數 對象

因爲C++引用傳進去的就是「別名」,因此在函數內對其進行的所有操做都將直接做用於實際的對象存儲空間上。 blog

產生這個困惑的緣由極可能是涉及到在函數(方法)中進行malloc(new)新的堆空間有關。其實這是一個比較有意思的問題。

咱們在新建一棵樹的時候,常常都會須要在新建函數(方法)中進行malloc(new)。固然,你可使用新建一個節點就做爲函數(方法)返回值進行返回。可是,通常人的思惟極可能是直接在函數裏面malloc(new),而後直接賦給傳入的表明樹的參數(T)。這種通常人的思惟方法大部分都是受到了嚴蔚敏《數據結構》的「荼毒」,而有沒有弄懂引用在Java和C++表明的不一樣意義而產生的錯誤。

誠然,咱們在C++中這樣來作是沒有問題的(參考嚴蔚敏《數據結構(C語言版)》P131),傳入了個BiTree &T而後(T = (BiTNode *)malloc(...)),很開心,測試一下OK了。

而後,在用Java寫樹的數據結構是仍是這麼幹,就出問題了。其主要的錯誤緣由是:Java中引用做爲傳參只是傳入個引用的COPY,這樣的在(T = new ...)以後,方法一結束,這個做爲引用的COPY就會被抹去,而在方法中的new對象因爲沒有引用(沒人指向它)也將做爲垃圾被回收掉。

咱們注意下其中涉及一個頗有趣的問題,這個問題是有關C語言中的malloc和JVM中的new的對象存儲空間的:

malloc和new產生的對象存儲都是發生在堆中的,而非棧。

而C++和Java的引用(包括引用COPY)都是在棧中的。

這麼說,其實它們的存儲結構是同樣的,可是卻因爲Java傳入的引用並不是真的引用,只是引用的COPY(有點像「狸貓換太子」),致使C++的樹實現方式可以實現,而相似地應用到Java中失敗!

這是個悲傷的故事。。。

相關文章
相關標籤/搜索