Правильная очистка CComSafeArray‹VARIANT›

Дано:

{
    CComSafeArray<VARIANT> sa;
    CComVariant ccv(L"test");
    sa.Add(ccv, TRUE);
}

Я надеялся, что dtor CComSafeArray вызовет ::VariantClear для каждого содержащегося члена, и документация, похоже, указывает, что:

В некоторых случаях может быть предпочтительнее очистить вариант кода без вызова VariantClear. Например, вы можете изменить тип варианта VT_I4 на другой тип, не вызывая эту функцию. У Safearrays BSTR будет вызываться SysFreeString для каждого элемента, а не VariantClear. Однако вы должны вызвать VariantClear, если VT_type получен, но не может быть обработан. У Safearrays of variant также будет вызываться VariantClear для каждого члена.

(источник: http://msdn.microsoft.com/en-us/library/windows/desktop/ms221165(v=vs.85).aspx)

Но я не вижу ничего подобного в коде atlsafe.h.

Я просто ищу не в том месте или это просто должно произойти как побочный эффект ::SafeArrayDestroy() - единственное, что происходит через CComSafeArray dtor.


person ForeverLearning    schedule 09.12.2014    source источник
comment
Трудно догадаться, где вы берете этот материал. Существует специализация шаблонного метода для CComSafeArray<BSTR>::SetAt(), но на этом микрооптимизации заканчиваются. Конечно, вы ищете не в том месте, вы не сможете увидеть исходный код SafeArrayDestroy или VariantClear, если только вы не работаете в Microsoft.   -  person Hans Passant    schedule 09.12.2014
comment
SafeArrayDestroy задокументирован следующим образом: Безопасные массивы варианта будут иметь функцию VariantClear, вызываемую для каждого члена, так что все должно быть в порядке.   -  person Simon Mourier    schedule 09.12.2014
comment
Это происходит как побочный эффект SafeArrayDestroy. Он выполняет правильную очистку каждого элемента в соответствии с типом элемента.   -  person Igor Tandetnik    schedule 09.12.2014
comment
Если один из вас, джентльмены, превратит это в ответ, я отмечу его как принятое.   -  person ForeverLearning    schedule 09.12.2014


Ответы (1)


В конечном итоге VariantClear будет вызываться для содержимого объекта CComSafeArray, хотя и после прохождения через несколько уровней. CComSafeArray::~CComSafeArray() вызывает CComSafeArray::Destroy(), который в конечном итоге является оболочкой SafeArrayDestroy():

HRESULT Destroy()
{
    HRESULT hRes = S_OK;
    if (m_psa != NULL)
    {
        hRes = Unlock();
        if (SUCCEEDED(hRes))
        {
            hRes = SafeArrayDestroy(m_psa);
            if (SUCCEEDED(hRes))
                m_psa = NULL;
        }
    }
    return hRes;
}

SafeArrayDestroy() задокументировано как вызов VariantClear на своем содержимое, если оно содержит ВАРИАНТЫ:

Безопасные массивы variant будут вызывать функцию VariantClear для каждого члена, а безопасные массивы BSTR будут вызывать функцию SysFreeString для каждого элемента.

person dlanod    schedule 05.06.2015