Если у меня есть [in,out] BSTR*
параметр, и я хочу изменить содержимое строки, но при этом сохранить ту же длину, могу ли я просто использовать его повторно или мне нужно перераспределить / освободить и выделить BSTR
?
За
[in, out]
параметры, вызывающая сторона выделяет память, метод или
собственность может по выбору освободить и перераспределить его, и вызывающий
наконец-то отвечает за удаление памяти.
Чтобы быть более полным, когда это необязательно?
когда это необязательно
В нем говорится, что вызывающая сторона отвечает за предоставление действительного аргумента (и выделение памяти, если необходимо).
Метод (вызываемый) также должен оставить параметр с допустимым значением. То есть, по своему усмотрению, он может оставить существующее значение на месте, или, по выбору, измените значение на другое — когда метод должен по какой-либо причине изменить параметр. Изменение выделяемого значения означает, что старое выделение должно быть отменено (освобождено), а новое выделение выполняется таким же образом, чтобы вызывающий абонент, получивший это значение, мог безопасно освободить, когда ему больше не нужно это значение.
Строковый параметр in / out будет выглядеть следующим образом. При первом выполнении он увеличивает первый символ входного значения без перераспределения, затем заменяет значение новым:
STDMETHOD(Method)(/* [in, out] */ BSTR* psValue) throw()
{
if(!psValue)
return E_POINTER;
static INT g_nCounter = 0;
if(++g_nCounter > 1)
{
// Deallocate old, Allocate new
SysFreeString(*psValue);
*psValue = SysAllocString(L"New Value");
} else
{
// No Re-allocation
if(SysStringLen(*psValue) > 0)
(*psValue)[0]++;
}
return S_OK;
}
Код на основе ATL может выглядеть немного лучше:
STDMETHOD(Method)(BSTR* psValue) throw()
{
_ATLTRY
{
ATLENSURE_THROW(psValue, E_POINTER);
CComBSTR& sValue = reinterpret_cast<CComBSTR&>(*psValue);
static INT g_nCounter = 0;
if(++g_nCounter > 1)
{
sValue = _T("New Value");
} else
{
if(sValue.Length() > 1)
sValue[0]++;
}
}
_ATLCATCH(Exception)
{
return Exception;
}
return S_OK;
}
Код стороны вызывающей стороны может быть таким:
CComBSTR sValue = _T("Old Value");
Method(&sValue);
CComBSTR sValueA = sValue; // Gets you "Pld Value"Method(&sValue);
CComBSTR sValueB = sValue; // Gets you "New Value"
Других решений пока нет …