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中失败!

这是个悲伤的故事。。。

相关文章
相关标签/搜索