COM学习笔记(二):引用计数

来源:互联网 发布:虚拟ip地址软件 编辑:程序博客网 时间:2024/05/16 20:31

IUnknown的另外两个成员函数AddRef和Release的作用就是给客户提供一种让它指示何时处理完一个接口的手段。

引用计数的三条规则:

1.在返回之前调用AddRef。对于那些返回接口指针的函数,在返回之前应用相应的指针调用AddRef。这些函数包括QueryInterface及CreateInstance。这样当用户从这种函数得到一个接口后,它将无需调用AddRef。

2.使用完接口之后调用Release。在使用完某个接口之后应调用此接口的Release函数。

3.在赋值之后调用AffRef.在将一个接口指针赋给另一个接口指针时,应调用AddRef。换句话说,在建立接口的另一个引用之后应增加相应组建的引用计数。
两条规则:
* pIUnknown = CreateInstance();
IX* pIX = NULL;
HRESULT hr = pIUknown->QueryInterface(IID_IX,(void**)&pIX);
pIUnknown->Release();//Done with IUnknown.
if(SUCCEEDED(hr)){
pIX->Fx(); //use interface IX.
pIX->Release();//Done with IX.
}
//第三条规则:
IUnknown* pIUnknown = CreateInstance();
IX* pIX = NULL;
HRESULT hr = pIUnknown->QueryInterface(IID_IX,(void** )&pIX);
pIUnknown->Release();
if(SUCCEEDED(hr)){
pIX->Fx();
IX* pIX2 = pIX;//非必须
pIX2->AddRef();
pIX2->Fx();
pIX2->Release();
pIX->Release();
}
AddRef和Release的实现:
ULONG __stdcall AddRef(){
return ++m_cRef;
}
ULONG __stdcall Release(){
if(--m_cRef == 0){
delete this;
return 0;
}
return m_cRef;
}
ULONG __stdcall AddRef(){
return InterlockedIncrement(&m_cRef);
}

ULONG __stdcall Release(){
if(InterlockedDecrement(&m_cRef) == 0){
delete this;
return 0;
}
return m_cRef;
}
引用计数规则:
1.输出参数规则:任何在输出参数中或作为返回值返回一个新的接口指针的函数必须对此接口指针调用AddRef。
2.输入参数规则:对传入函数的接口指针,无需调用AddRef和Release,这是因为函数的生命期潜逃在调用者的生命期内。
3.用输入-输出参数传进来的指针:必须在给它赋另外一个接口指针之前调用其Release。在函数返回之前,还必须对输出参数中所保存的接口指针调用AddRef。

eg:
void ExchangeForCachedPtr(int i,IX** ppIX){
(*ppIX)->Fx();
(*ppIX)->Release();
*ppIX = g_Cache[i];
(*ppIX)->AddRef();
(**ppIX)->Fx();
}
4.局部变量规则:无需调用AddRef和Release。
5.全局变量规则:对于保存在全局变量中的接口指针,再将其传递给另外一个函数之前,必须调用其AddRef。由于此变量时全局性的,因此任何函数都可以通过调用其Release来终止其生命期。对于保存在成员变量中的接口指针,也应按此种方式处理。



0 0