函数返回CComPtr<IMFSample>是否合规?引用计数是否正确?
这种做法完全可行,而且是COM编程中推荐的最佳实践之一,引用计数也会保持正确!
CComPtr作为ATL的智能指针,核心作用就是自动管理COM对象的引用计数,所以直接返回CComPtr<IMFSample>是非常合理的。具体原理是:
- 当你在函数内部通过
MFCreateSample或其他COM创建函数初始化CComPtr<IMFSample>时,智能指针会自动调用AddRef持有对象引用。 - 函数返回时,
CComPtr的拷贝构造函数会自动对对象调用一次AddRef,把引用传递给调用者的智能指针。 - 函数内部的局部
CComPtr实例在函数退出时会被销毁,自动调用Release——此时对象的引用计数会减去1,刚好和返回时的AddRef抵消,最终调用者持有的引用计数完全正确。
下面是修正后的完整示例函数:
CComPtr<IMFSample> getSample() { HRESULT hr = S_OK; CComPtr<IMFSample> pSample; // 创建IMFSample实例 hr = MFCreateSample(&pSample); if (FAILED(hr)) { // 错误处理:直接返回空指针,局部pSample会自动释放(如果已创建) return nullptr; } // 为Sample添加缓冲区的示例逻辑 const DWORD bufferSize = 4096; CComPtr<IMFMediaBuffer> pBuffer; hr = MFCreateMemoryBuffer(bufferSize, &pBuffer); if (SUCCEEDED(hr)) { // pBuffer的引用会被IMFSample持有,无需手动管理 hr = pSample->AddBuffer(pBuffer); } // 如果中途出错,pSample会自动释放已创建的对象;成功则返回有效引用 return pSample; }
额外补充几点注意事项:
- 绝对不要在返回前手动调用
pSample->AddRef(),否则会导致引用计数多增一次,最终造成内存泄漏。 - 调用者使用时直接用
CComPtr<IMFSample> mySample = getSample();即可,无需手动调用Release,智能指针会在生命周期结束时自动清理。 - 如果函数中途失败返回
nullptr,内部所有已创建的CComPtr(包括pSample和pBuffer)都会自动销毁,正确释放对应的COM对象,不会产生泄漏。
内容的提问来源于stack exchange,提问作者Gary G.
相关产品推荐
相关产品推荐

