1. 生命期控制
當使用完一個接口而仍要使用另外一個接口時,是不能將此組件釋放掉的。很難知道兩個指針是否指向同一個對象。IUnknown的另外兩個函數AddRef和Release來指示合適處理完一個接口的手段。
2. 引用計數簡介
AddRef和Release實現的時一種名爲引用計數的內存管理技術。引用計數是使組件能夠自己將自己刪除的最簡單同時也是效率最高的方法。當客戶從組件取得一個接口時,此引用計數就增加1,使用完某個接口後組件將引用計數減1,當引用計數爲0的時候組件將自己從內存中刪除。
- 在返回之前調用AddRef。對於那些返回接口指針的函數,在返回之前應用相應的指針調用AddRef,這樣當客戶從函數獲得一個接口後就無需調用AddRef
- 使用完接口之後調用Release。在使用完某個接口之後應調用此接口的Release函數。
- 在賦值之後調用AddRef。在講一個接口指針賦值給另外一個接口指針時,應調用AddRef。
引用計數接口
從客戶來看:每一個接口都有一個引用計數。從組件來看:組件可以維護一個引用計數。
爲每個接口都有一個引用計數而不是針對組件維護,原因:
1、 是程序調試更爲方便
2、 支持資源的按需獲取
在實現某個接口時可能需要大量的內存或者其他資源,可以在QueryInterface中實現,在客戶請求此接口時完成資源的分配。但若只對組件維護一個引用計數那麼組件將無法決定何時可以安全將同此接口相關的內存釋放。
AddRef和Release的實現
ULONG __stdcallAddRef()
{
return InterlockedIncrement(&m_cRef);
}
ULONG __stdcallRelease()
{
if(InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
何時使用引用計數—引用計數規則
- 輸出參數規則
輸出參數指給函數的調用者傳會一個值的函數參數,在函數體中設置此參數的值。任何輸出參數或返回值返回一個新的接口指針的函數必須對此接口指針調用AddRef。
- 輸入參數規則
輸入參數指給函數傳遞某個值的參數,在函數體中會使用這個值但不會修改它。對傳入的接口指針無需調用AddRef和Release,因爲函數的生命期嵌套在調用者的生命期中。
- 輸入-輸出參數規則
輸入-輸出蠶食同時具有輸入參數及市場參數的功能,在函數體中可以使用輸入-輸出參數的值。在函數中對於輸入-輸出參數傳遞進來的接口指針,必須在給他賦另外一個接口指針值之前調用Release。在函數返回之前,還必須對輸出參數中所保持的接口指針調用AddRef。
- 局部變量規則
對於局部複製的接口指針,由於只是在函數的生命期內才存在,因此無需調用AddRef和Release
- 全局變量規則
對於保持在全局變量中的接口指針,在講起傳遞給另外一個函數之前,必須調用AddRef