With Microsoft::WRL::ComPtr
I prefer the use of ReleaseAndGetAddressOf
and GetAddressOf
rather than using the operator&
overload. There's a few reasons for this.
The older ATL CComPtr when using operator&
is equivalent to GetAdddressOf
with an assert to assume it was nullptr to being with. The WRL ComPtr uses ReleaseAndGetAddressOf
which is the safer default to avoid potential resource leaks, but can also cause confusion when you can end up with 'nullptr' results when you didn't expect it such as trying to pass a pointer-to-a-pointer often used in Direct3D APIs.
This design point was driven by a common pattern in all COM code:
ComPtr<IWICImagingFactory> ifactory;
hr = CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&ifactory));
With ATL CComPtr, this only works if ifactory
is in fact nullptr (always true for a local variable but not necessarily for global or class member variables). The WRL ComPtr will always check for non-null and release it if needed, which is more robust but may be unnecessary as in the case of a local variable.
The choice, however, makes for problems for Direct3D usage of COM interfaces. For example, the following code is NOT going to work correctly with WRL ComPtr (the RTV will be cleared before you try to set it) and will assert with ATL's CComPtr in DEBUG builds.
context->OMSetRenderTargets(1, &m_renderTargetView,
m_depthStencilView.Get());
You can get it to work as:
context->OMSetRenderTargets(1, m_renderTargetView.GetAddressOf(),
m_depthStencilView.Get());
But it's probably even clearer to the future reader to do:
auto rt = m_renderTargetView.Get();
context->OMSetRenderTargets(1, &rt, m_depthStencilView.Get());
In the code snippet from Luna above, it's a safer choice to use .ReleaseAndGetAddressOf
since the method being called is a creation fucntion and the member variable could already be set. This would avoid memory leaks even when the class is 'misused. I prefer to use .GetAddressOf
if I'm initializing a local variable that I know was just created so it's always nullptr.
See this wiki page for more advice.