Назначение ComBSTR

Я запутался в назначении строк COM. Какое из следующих назначений строк является правильным. Почему?

CComBSTR str;
.
.
Obj->str = L""  //Option1

ИЛИ должно быть

Obj->str = CComBSTR(L"")  //Option2

Какова причина


person Julian    schedule 16.11.2009    source источник


Ответы (4)


Если вы используете str = CComBSTR(L""), вы используете конструктор:

CComBSTR( LPCSTR pSrc );

Если вы используете str = L"", вы используете оператор присваивания:

CComBSTR& operator =(LPCSTR pSrc);

Оба они правильно инициализируют объект CComBSTR.

person Nestor    schedule 16.11.2009

Настоящий BSTR это:

  • временно выделенный из кучи COM (через SysAllocString() и семейство)
  • структура данных, в которой строковым данным предшествует их длина, хранящаяся в 32-битном значении.
  • передается как указатель на пятый байт этой структуры данных, где находятся строковые данные.

См. документацию: MSDN: BSTR

Большинство функций, которые принимают BSTR, не будут аварийно завершать работу при передаче BSTR, создающей простое назначение. Это приводит к путанице, поскольку люди наблюдают за тем, что кажется работающим кодом, из которого они делают вывод, что BSTR можно инициализировать точно так же, как любой WCHAR *. Этот вывод неверен.

В интерфейсы OLE Automation можно передавать только реальные BSTRs.

Используя конструктор CComBSTR(), который вызывает SysAllocString(), ваш код создаст настоящий BSTR. Деструктор CComBSTR() позаботится о возврате выделенного хранилища в систему через SysFreeString().

Если вы передаете CComBSTR() API, который становится владельцем, обязательно вызовите метод .Detach(), чтобы гарантировать, что BSTR не будет освобожден. BSTRs не подсчитываются ссылки (в отличие от COM-объектов, которые учитываются), поэтому попытка освободить BSTR более одного раза приведет к сбою.

person Heath Hunnicutt    schedule 16.11.2009

Лично я бы предпочел вариант 1, потому что он не требует создания нового объекта CComBSTR. (Конечно, делает ли это их код за кулисами, это другая история.)

person Chris Jester-Young    schedule 16.11.2009

Вариант 1 предпочтительнее, потому что он делает только одно выделение для строки, тогда как вариант 2 делает 2 (несмотря на создание нового временного объекта без особой причины). В отличие от типа bstr_t в VC++, тип ATL не делает ссылки на подсчитываемые строки, поэтому он будет копировать всю строку.

person tyranid    schedule 16.11.2009