20160218:
我对类的实例所占用的内存有个误区:我认为类的实例的内存大小为其下所有成员变量的内存之和,它可能占内存里的一大块区域。
比如:Class A{
private int i;
},在堆内存里new一个A的实例a,请问a的内存大小是多少?是4个字节吗?
站在内存的角度上,它只分配了4个字节的空间给成员变量i,但它根本不知道什么是实例,因为实例是一个抽象的概念。所以我认为a没有占用任何内存,倒是它的成员变量i占有内存。
那么我们销毁a的时候,内存释放了吗?什么都没有释放,因为它就没占用内存。我们要真正要释放的是a下面的成员变量i的内存。我们平时所谓的销毁a,导致内存的释放,其实是因为垃圾回收帮忙了,a的销毁导致i的引用丢失,进而销毁了i,这才释放了内存。
也就是说,不管类的实例怎么置null,如果不能让它的成员变量引用丢失,那么内存是不会释放的。以上是我的一点看法。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
20160224:
之前的理解还是有误区,事实上类的实例的内存大小确实可以理解成其下
所有成员变量的内存之和,只是要搞清楚变量本身占用的内存和变量所指向的内存的区别。
以C#为例:Class A{ private Integer i = new Interger(10); },同样new一个A的实例 a。
之前我只盯着
new Interger(10)这块开辟出来的堆内存,它是4个字节没错。但是不要忽略了i这个变量本身是占用内存的,i是一个引用,存储的是一个地址,在64位机器上8个字节表示地址,所以i本身的内存是8字节,它指向一个4字节的堆内存。这个时候再引发两个概念:生命周期、垃圾回收。实例和实例的成员是共生命周期的,所以销毁对象a,a下面的所有成员都会被销毁,意味着i所占用的8个字节被销毁了。但是i指向的4个字节的堆内存没有被直接销毁,是需要等垃圾回收销毁的。
引申到C++:同样有生命周期,但没有垃圾回收。所以C++程序员在销毁对象a时,必须在析构函数里delete i,才能释放i指向的内存。当然C++有堆对象和栈对象的区别,只有new出来的堆对象需要显示delete,也就是一个new对应一个delete。