關鍵字:數據庫設計由于很多垃圾回收算法都是在編譯器層面實現的,而編譯器層面實現起來牽涉的內容很復雜,一般軟件人員理解起來很困難,實際上他們也沒有必要去詳細了解編譯器層面的垃圾回收算法是如何實現的,為了講清楚垃圾回收的原理,我們還是以一個用戶程序層面的垃圾回收算法的具體實現來進行講解。
前面提到,引用計數算法簡單易懂,且可以在用戶程序層面實現,下面就以引用計數算法來實現一個C++用戶程序層面的垃圾回收算法。
1. C++用戶程序層的垃圾回收實現原理
首先要了解清楚C++用戶程序層的垃圾回收實現原理,引用計數算法中,如何對一個已分配內存進行計數的增減操作呢?先看一段C++的程序吧。
int *p;
{
int *q = new int;
*q = 100;
p = new int;
*p = 200;
}
在這段程序中,當執行“*q= 100;”語句時,需要對分配的內存引用計數加1,當退出大括號“}”后,由于指針變量q已經被編譯器釋放掉了,所以這時指向的內存的引用計數要減1。但在上面這段程序中,是沒有實現引用計數功能的。要實現引用計數功能,就必須執行int *q = new int;這樣的語句能自動給分配的內存增加引用計數,而指針變量q釋放時由于是編譯器實現的,用戶程序并不知道,所以還需要找到發現變量被編譯器釋放的方法。
2. 模擬指針的C++實現
如果可以設計一個類來模擬指針,那么就可以利用類的構造函數和析構函數來操作指針變量的引用計數,幸運的是C++中的語法提供了這種功能,可以通過重載運算符“*”、“,”、“=”和“->”來實現。
template <class T> class GCPtr {
T *m_pAddr;
public:
GCPtr(T *t=NULL){m_pAddr = t;};
~GCPtr();
T &operator*() { return *m_pAddr;};
T *operator->() { return m_pAddr;};
T *operator=(T *t) { m_pAddr = t;};
GCPtr & operator=(GCPtr &r) { m_pAddr = r.m_pAddr;};
};
在通過如下方式定義一個對象p時:
GCPtr<int> p;
可以將對象p如int類型指針一樣來使用,實際的操作都是通過重載運算符來操作GCPtr類里面的pAddr成員實現的。
有了模擬指針,就可以通過類GCPtr來定義任意類型的指針。只要在GCPtr的構造函數和析構函數里進行引用計數的增減,就可以實現引用計數方法的垃圾回收了。
也許有些讀者認為可以直接在析構函數里將指針指向的內存釋放,但這個想法是在只有這一個指針指向釋放的內存的情況下才可行,如果有其他指針指向同一塊內存,并且其他指針的生存期更長,就會出現程序運行異常,下面可以看一段簡單的程序。
GCPtr<int> p;
p = new int;
{
GCPtr q;
q = p;
}
*p = 100;
以上這段程序中p和q指向的是同一塊內存,如果在析構函數中直接將內存釋放,那么“*p=100;”這條語句將出現異常,所以不能簡單地將一塊內存釋放掉,必須確認沒有指針指向它時才可以釋放。因此必須給內存加上引用計數,有多少個指針指向它,計數就為多少,如果引用計數為0就表示沒有指針指向它,這時才可以將內存釋放掉。
3. 引用計數的實現
上面實現了一個模擬指針的功能,要將模擬指針變成一個具有引用計數功能的模擬指針,首要問題就是要為每塊分配的內存找一個保存引用計數的地方。
文章來源于領測軟件測試網 http://www.kjueaiud.com/