11

Why is a QueryInterface() call always followed by a Release() call? For example, I have seen a sample code from MSDN as below:

HRESULT hr = S_OK;
CDecoder *pObj = new CDecoder(&hr);

if (SUCCEEDED(hr))
{
    *ppv = NULL;
    hr = pObj->QueryInterface(riid, ppv);
}
pObj->Release();
return hr;

can someone explain the intent behind Release() call here?

4

3 回答 3

16

它并不总是像这样直接遵循,尽管这很常见。

COM 对象是引用计数的。最初创建对象时,您会得到一个指向IUnknown. 然后你会得到一些其他的接口QueryInterface。由于您(通常)不再关心IUnknown界面,因此您将其释放。当您释放您获得的另一个接口时,引用计数将为0,因此可以销毁该对象。但是,如果您不释放IUnknown,则引用计数将保持非零,因此无法销毁对象。

您不会立即发布的最明显情况IUnknown是何时/如果您需要获得多个其他接口。在这种情况下,您将获得IUnknown,然后是第二个和第三个接口,然后再释放IUnknown. 至少在某些情况下,您可能在创建对象后不知道第三个(或后续)接口,因此您可能需要IUnknown在释放它之前保留对任意时间长度的访问。

于 2011-02-18T23:43:25.250 回答
8

Why is a QueryInterface call is always followed by a Release call?

Because QueryInterface will call AddRef which increases the reference count to the pointer. When there are 0 references to a pointer it is freed for you.

Note: There is some confusion in this question's answers about what QueryInterface actually does. It simply retrieves pointers to the supported interfaces on an object and increments the reference count on that object. It doesn't create a new object for each interface that it implements.

For example if you have an object which implements 2 interfaces, then the call would simply cast that object as each of the interface and increment a variable which is used as the reference count.

Note: The reference counting can be implemented in different ways, but the above explains the usual scenario. In particular @Ben describes a tear off interface below which stresses the importance of calling Release on the interface pointer that was returned to you.

于 2011-02-18T23:39:07.513 回答
4

这个特定的代码片段似乎只对获取ppv值感兴趣。请注意,它不是释放接口指针。CDecoder 类似乎是获得它的工具。有一个的语句来创建它,而不是创建 COM 类的标准 COM 方法,它采用 CoCreateInstance()。显然,该类的正确使用需要 Release() 调用而不是使用delete运算符。同样,一点也不标准,但并非不可能。我只能猜测 CDecoder 是一个实现 COM coclass 的 C++ 类,并且此代码直接使用它,而不是通过正常的 COM 过程。

不要假设此代码是标准的。根本不是。

于 2011-02-19T00:43:11.470 回答