打容指针有副作用吗?
对性能和内存有一定影响,但不大(相对于直接使用数组),在一般情况下是可以接受甚至忽略的; 打引用计数的目的主要是为了让垃圾回收器能够更好地扫描和回收对象。
打引用的过程实际上就是记录对象被引用的次数,当达到设定的阈值时,就会被警告或报告错误。这个数值一般可以在编译器中指定,比如gcc(g++)中的-Wunused即可设置此值。
举个例子: 如果有一个变量a指向一个对象,那么打印出a所对应的地址值后,再在程序里任意输入几个变量b、c、d,如果这些变量的类型也是指针类型或者引用类型,并且它们分别指向同一块内存区域,那么这时再输出的a的值就不会变了——因为所有的指针都指向同一块内存,也就是说所有指针的“计数”都是相同的。而如果改变其中一个变量的值,其他变量所关联的指针就会自动减小1。
所以通过这种方法,垃圾回收器可以知道什么时候需要整理内存空间。 但是如果没有进行打引用操作,那么在上面的例子中,不论输入的是什么,a的值都会发生变化!即所有的“计数”都是一个新的值,这样垃圾回收器就不能准确地判断何时需要整理内存了。因此如果不打引用,那么无论是否使用了内存池技术,虚拟机都必须定期地主动扫描整个程序执行环境来检测没有任何引用的对象,进而确定是否可以回收。
这不仅会降低程序的性能,更重要的是它会让虚拟机的内存管理工作变得非常复杂!为了应对可能的情况并提高内存使用的效率,现代的Java虚拟机都提供了一种名为“内存优化”的功能。它的原理是在第一次使用某个对象的时候,并不是真正地对它进行分配,而是将这个对象的元数据(包括对象引用数)存储起来,直到达到一定条件之后再实际分配内存。这种机制能够极大程度地提升性能而且并不增加太多的复杂性。
另外要说明的是,打引用并不会消耗更多的内存,因为它只是简单地记录变量的值,而不是真正创建一个新的对象(当然,打引用的过程中会创建一些临时对象,但是这些对象会在下次打引用或者垃圾收集时消失)。