irrlicht引擎原始碼剖析 引用計數

2021-05-22 16:34:14 字數 2286 閱讀 7633

在研究irrlicht的video driver和scene graph之前,必須先了解在irrlicht中廣泛應用的引用計數機制。irrlicht的介面ireferencecounted實現了引用計數的機制。需要採用引用計數管理的類都會繼承這個介面。irr的引用計數最重要的兩個介面就是grab()和drop()。

view plaincopy to clipboardprint?

bool drop() const 

return false;  

}  bool drop() const

return false;

} grab()只是簡單的將引用計數加一,而drop()是這個機制的核心,當drop()後當引用計數為0時,物件例項通過delete this刪除自己從而最終釋放了無人再使用的物件。正確的使用grab()和drop()是引用計數機制的核心,當你想長期持有乙個物件時,需要grab()他,然後在不再使用的時候drop()他。grab()後,這個物件就不會因為其他地方的drop而被釋放掉,因為至少你還有對他的引用。如果只是在乙個函式段裡面短期的使用乙個物件,可以不grab也不drop,當然你要考慮多執行緒的情況。另外如果物件是你建立的,但你不能決定什麼時候釋放他,你就應該再把該物件新增到某個物件後呼叫drop(),這種情況也很常用。比如下面的偽**:

iimage* pimage = new cimage(...);

pimagemanager->add(pimage); //in add, pimagemanager will call a grab()

pimage->drop();

這樣很容易將物件的建立和釋放分開到不同的物件中。

當然引用計數機制也讓很多人討厭,因為用亂了用錯了麻煩一大堆。如果是自己建立的物件還好,而irrlicht引擎中提供的物件就要小心對待了。一般說來使用get***()得到的物件不需要drop(),當然除非你grab()了。使用create***()或你自己new出來的物件,你需要保證他在某個地方被drop()了,實在不放心應該深入引擎的**看一下,建議使用vld這樣的視覺化記憶體洩露監測工具幫助你查詢洩露記憶體的地方。

另外還有兩個值得注意的問題

1)ireferencecounted介面往往是被虛擬繼承的,例如

class iscenemanager : public virtual ireferencecounted

因為使用引用計數的介面和類很多,有可能某個類實現了幾個介面,而這幾個介面都繼承自ireferencecounted, public virtual繼承保證只有乙個ireferencecounted基類物件

例如class cscenemanager : public iscenemanager, public iscenenode就是這種情況

因為:class iscenenode : virtual public io::iattributeexchangingobject

class iattributeexchangingobject : virtual public ireferencecounted

而class iscenemanager : public virtual ireferencecounted

2)觀察一些irrlicht引擎中的介面,介面中沒有定義虛擬的析構函式

例如class imesh : public virtual ireferencecounted,在include/imesh.h中

這個介面裡面連~imesh()都沒有,更不會有virtual ~imesh()了。

按照c++通常的思維,如果乙個類明確的是要被繼承的,需要定義乙個virtual析構。那麼為什麼irrlicht中的很多介面都不定義呢?正因為他是引用計數的。比如,有乙個介面ibase和他的子類cderived。如果這麼用

ibase* pbase = new cderived();

那麼當delete pbase時,如果ibase沒有虛擬析構,就不會正確執行cderived的析構了。

但是如果ibase繼承自ireferencecounted,通常我們的用法不會使用delete pbase來釋放這個物件了。我們會使用pbase->drop(),問題就在這兒,這個drop()就是ireferencecounted介面定義的那個,最終會執行delete this,這個this的型別就是呼叫drop()的物件的型別,這個物件實際是子類的,所以會呼叫子類的析構函式,從而會進一步呼叫父類的析構,所以父類沒有定義虛擬析構也不要緊了。這就是引用計數的花招。當然irrlicht引擎中有些介面也定義了虛擬析構,這沒有影響,這樣更安全,即使某人沒有用引用計數的方法管理物件的生命週期也不會出問題。我覺得,無論是否使用這樣的引用計數機制,最好給父類都加上虛擬析構比較安全,也比較明確。

irrlicht引擎原始碼剖析 引用計數

在研究irrlicht的video driver和scene graph之前,必須先了解在irrlicht中廣泛應用的引用計數機制。irrlicht的介面ireferencecounted實現了引用計數的機制。需要採用引用計數管理的類都會繼承這個介面。irr的引用計數最重要的兩個介面就是grab 和...

Irrlicht引擎原始碼剖析 第三天

今天開始看include core部分,首先開啟irrmath.h,該檔案在core命名空間裡定義了4個常數,如浮點數比較時的捨入精度,圓周率,以及用於角度與弧度之間轉換的常數值。接著看vector2d.h,該檔案實現了乙個2d向量的模板類,以其相關方法的定義。因為該類中的normalize 方法的...

Irrlicht引擎原始碼剖析 第二天

我們來看看irrlicht.h檔案中宣告的建立引擎裝置物件的函式的形參 irrlicht api irrlichtdevice createdevice video edrivertypedevicetype,const core dimension2d windowsize,u32 bits,bo...