引用计数就是程序中有多少地方使用了某个对象。每当程序的一个部分需要某个对象时,则对该对象的引用计数加1。如果不再需要相应的对象,则对该对象的引用计数减1。在计数下降到0后,程序知道不再需要该对象,所以此时从内存中释放该对象。
为什么需要引用计数呢?
一,引用计数提供了线性安全的对象生命周期管理。
例如,两个线程都拥有同一个对象指针的使用权,到了某个时刻,其中一个线程不需要这个对象了,但是,它不能随便释放掉这个对象,因为它不知道另外的一个线程是否还在使用这个对象。一般我们想到的解决的方法是,通过同步加锁来实现,但是还是很繁琐。
引用计数可以很好解决上述的问题,当其中一个线程不需要某个对象了,计数减一就可以,无论这个对象是否真的被释放,这已经不是当前线程考虑的问题。最后一个用到这个对象的地方,自会释放掉这个对象的。
二,引用计数,提供了夸语言,夸模块的对象生命周期管理。
例如,我们有一个用c++编写成dll模块,其中里面的某个函数返回的是一个对象指针(对象是new出来的),使用完这个对象指针之后,就需要释放的这个对象。那如何释放这个对象?直接delete? 当然不行,例如:dll是被delphi使用的话,那怎么delete? 就算是是给c++使用,也是不能直接delete,这样会导致程序崩溃(对象哪个模块生成,哪个模块删除)。所以,我们就不得不提供一个释放对象的函数,这样的函数也是不通用的,加大了编程的难度。
引用计数是解决对象的生命周期的设计,当然也能解决这个问题。一般我们要实现具有引用计数的对象,都是给对象引出两个成员函数,例如:AddRef() 和 Release() (可以是其他名字,这个只是COM里面的定义)。只要你给上述的对象指针,Release()一下,对象就释放掉了。
三,引用计数,还提高拷贝效率。 因为,引用计数对象是以指针形式存在, 不用拷贝构造,效率自然高了。
最后,在多线程程序里面,引用计数不能直接通过++,--,来控制,因为多个线程,可能同时操作引用计数,这样可能导致多次释放同一对象或者内存泄漏。那需要加锁? 不需要,因为操作系统会提供原子增和原子减的函数,来保证正确加减。windows下面对应两个函数InterLockedIncrement 和 InterlockedDecrement 。