c++ 为什么每个成功的QueryInterface()调用后面都跟着Release()调用?

cbwuti44  于 2022-12-20  发布在  其他
关注(0)|答案(3)|浏览(109)

为什么QueryInterface()调用总是跟在Release()调用后面?例如,我在MSDN上看到了下面的示例代码:

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

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

有人能解释一下Release()调用背后的意图吗?

8ljdwjyq

8ljdwjyq1#

它并不总是像这样直接遵循,尽管这是很常见的。
COM对象是引用计数的。当你最初创建对象时,你会得到一个指向IUnknown的指针。然后你会得到QueryInterface的其他接口。因为你(通常)不关心IUnknown接口了,你把那个释放了,当你把你得到的另一个接口释放了,引用计数将为0,因此对象可以被销毁。但是,如果您不释放IUnknown,引用计数将保持非零,因此对象不能被销毁。
最明显的情况是,如果您需要获得多个其他接口,您就不会立即释放IUnknown。在这种情况下,您将获得IUnknown,然后在释放IUnknown之前获得第二个和第三个接口。至少有可能您不知道第三个接口(或后续)接口,因此在释放IUnknown之前,可能需要将其访问权限保留任意长的时间。

hfyxw5xn

hfyxw5xn2#

为什么QueryInterface调用后面总是跟一个Release调用?
因为QueryInterface将调用AddRefAddRef将增加对指针的引用计数。当对指针的引用为0时,指针将被释放。
注意:在这个问题的答案中有一些关于QueryInterface实际功能的混淆。它只是检索一个对象上支持的接口的指针,并增加该对象上的引用计数。它不会为它实现的每个接口创建一个新的对象。
例如,如果你有一个实现了2个接口的对象,那么调用会简单地将该对象转换为每个接口,并增加一个用作引用计数的变量。
注意:引用计数可以用不同的方式实现,但上面解释了常见的场景。特别是@Ben描述了一个分离接口,它强调了在返回给你的接口指针上调用Release的重要性。

oipij1gg

oipij1gg3#

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

相关问题