这个CComSafeArray使用不好吗?

Is this CComSafeArray usage bad?

本文关键字:CComSafeArray 这个      更新时间:2023-10-16

有一个COM函数:

GetData(SAFEARRAY ** pRetVal)

和以下遗留代码:

CComSafeArray<double> saDataArray;
hr = pmyInterface->GetData(&saDataArray.m_psa);
SafeArrayLock(saDataArray);

我怀疑手动管理锁是否好。当m_psaGetData返回为NULL时,代码会崩溃吗?

下面的代码如何?这样好点了吗?

LPSAFEARRAY psa;
CComSafeArray<double> saDataArray;
hr = pmyInterface->GetData(&psa);
saDataArray.Attach(psa);
编辑:

我测试了上面的两个代码。有一点不同。如果GetData返回NULL,直接Attach而不检查NULL会调用异常。第一个版本将返回一个E_INVALIDARG。我的问题仍然存在,你更喜欢后来的版本,因为它使用SafeArray对象来维护计数,而不是混合它?

EDIT2: 如果出于某种原因我选择了第一个版本,可以忽略E_INVALIDARG返回值吗?当一些代码以后使用这个saDataArray时,这会有任何副作用吗?

您写的:

SafeArray * psa;
CComSafeArray<double> saDataArray;
hr = pmyInterface->GetData(&psa);
saDataArray.Attach(psa);

但是我认为实际的代码应该是:

LPSAFEARRAY psa; // not "SafeArray *"
hr = pmyInterface->GetData(&psa);
CComSafeArray<double> saDataArray;
saDataArray.Attach(psa);

详情请参见此问题。

EDIT:根据你的问题编辑更新答案

我真的不喜欢你的第一个代码:

CComSafeArray<double> saDataArray;
hr = pmyInterface->GetData(&saDataArray.m_psa);
SafeArrayLock(saDataArray); // <--- Explicit lock on a CComSafeArray-wrapped array

事实上,一旦原始的SAFEARRAY给了一个c++ RAII包装器(CComSafeArray),从那时起,我只会使用这个包装器和它的方法来操作数组。
如果你想对数组进行"手动"处理,只需从c++包装器中.Detach()它,并使用Win32 API函数调用。但是在我看来,混合两者并不是高质量的代码。

注意第二种方法是不同的,因为您首先使用原始的SAFEARRAY,使GetData()方法填充它,然后您将其.Attach()CComSafeArray c++ RAII包装器,将所有权("移动语义")转移到该包装器。然后就可以使用包装器方法来操作数组了。

此外,在生产质量代码中,我不会忽略错误HRESULT s。