Posted on 2010-07-23 10:27
亂78糟 閱讀(5812)
評論(0) 編輯 收藏 引用 所屬分類:
C語言派系
一、什么是引用計數?
引用計數是內存管理的一個技巧,可以看做是一種簡單的垃圾回收機制,它允許多個擁有共同值的對象共享同一個對象。
二、為什么采用它?
對于沒有垃圾自動回收機制的語言(如C/C++)和技術(如COM)來說,引用計數提供了一種簡潔高效的內存管理方法。
一個對象被從堆中分配出來之后,我們需要明確的知道是誰擁有了這個對象,因為只有擁有這個對象的所有者能夠銷毀它。但我們在實際使用過程中, 這個對象可能被傳遞給另一個對象(例如通過傳遞指針參數),一旦這個過程復雜,我們很難確定誰最后擁有了這個對象。
使用引用計數就可以拋開這個問題,我們不需要再去關心誰擁有了這個對象,因為我們把管理權交割給了對象自己(這有點類似__stdcall和__cdecl兩種函數調用約定)。當這個對象不再被任何人使用時,它自己負責銷毀自己。
簡單是特定時候增減一下對象的引用計數就可以了。高效是讓多個具有相同值的對象共享同一個對象,省卻了拷貝復值的過程,而且更加節省內存和寶貴的CPU時間。
三、誰都在使用它?
現在很多技術和編程語言都在使用它,如COM,Object-C等,如果我們愿意,我們可以在自己的程序中使用它。
IUnknow提供了三個接口:QueryInterface、AddRef、Release。后面兩個分別用來增減和減少通過QueryInterface獲取的接口對象的引用計數,當內部的計數為0時,接口對象自動銷毀自身。
這種類型的DLL包含四個導出函數:DLLRegisterServer、DLLUnregisterServer、DLLGetClassObject、DLLCanUnloadNoew。最后一個函數就是通過查看DLL維護的組件的計數值來決定這個DLL是否可以被CoFreeUnusedLibraries卸載掉。
Object-C作為C的派生語言,它的內存管理徹底的采用了這個技巧。它的Foundation框架提供了是哪個方法:autoreleae、retain、release。第一個是將一個對象交由自動釋放池管理,其實是自動調用了release;后面兩個和COM中的最后兩個是相同的,分別用來增加和減少引用計數。
四、我該如何實現它?
下面我給出一個很簡單的例子,演示如何實現引用計數。
class Foo{
public:
Foo(){
_ref = 1;//構造成功之后計數即為1
}
//輔助,用來打印引用計數
void Print(){
std::cout << "_ref = " << _ref << std::endl;
}
public:
//增加引用計數
ULONG AddRef(){
return InterlockedIncrement(&_ref);
}
//減少引用計數
ULONG Release(){
if (0 == InterlockedDecrement(&_ref)){
delete this;
return 0;
}
return _ref;
}
private:
long _ref;
};
int main(int argc, char *argv[])
{
Foo * foo = new Foo;
foo->Print();//輸出:_ref = 1
foo->Release();
foo->Print();//輸出:_ref = 隨機數字
return 0;
}
PS: 這里是云風寫的一篇文章
《引用計數與垃圾回收之比較》,我認為寫的非常好。