2

我有一个 ATL COM 组件方法,它将 BSTR 作为 in 参数。我需要在一个数组中添加对该方法的每个调用。我不能使用 SAFEARRAY,因为它是固定大小的,所以我认为 std::vector 将是最简单的选择。当然,我需要为向量的每个添加调用 SysAllocString。这意味着在销毁向量之前,需要为每个条目调用 SysFreeString。

我正在寻找一个更简单/更清洁的解决方案,并考虑将向量声明为 vector<_bstr_t> ,其中包括自动清理。然而,在我的脑海里,有一些事情正在引发警报,因为它实际上是一个标准容器中的智能指针。我的担心是合理的还是我可以安全地做到这一点?如果没有,还有其他更好的解决方案吗?

4

4 回答 4

4

[关于vector< _bstr_t >]我的担心是否合理,或者我可以安全地这样做吗?

是的。虽然您可以放心使用,但请_bstr_t记住,它不仅是一个智能指针,而且还是一个引用计数的智能指针。这意味着额外的费用。

如果没有,还有其他更好的解决方案吗?

我通常会使用 aCComBSTR而不是BSTRor _bstr_t。如果您需要引用计数,那么您必须依靠_bstr_t. 例如:如果您还使用 ATL,您可能只需要CComBSTRs。

CComBSTR 类是 BSTR 的包装器,它是长度前缀字符串。长度以整数形式存储在字符串中数据之前的内存位置。

BSTR 在最后一个计数字符之后以空字符结尾,但也可能包含嵌入在字符串中的空字符。字符串长度由字符数决定,而不是第一个空字符。

因此,在做出选择之前,请考虑以下几点:

  1. _bstr_t是一个引用计数的智能指针包装器,而不BSTR提供任何引用计数。CComBSTR
  2. _bstr_t 不会重新定义地址操作符,因此可以安全地存储在 STL 容器中。与CComBSTR您将需要使用CAdapt.

关于CAdapt对象:

CAdapt 是一个简单的模板,用于包装重新定义地址运算符(运算符 &)以返回对象地址以外的其他内容的类。此类类的示例包括 ATL 的 CComBSTR、CComPtr 和 CComQIPtr 类,以及编译器 COM 支持类 _com_ptr_t。这些类都重新定义了地址运算符以返回其数据成员之一的地址(在 CComBSTR 的情况下为 BSTR,在其他类的情况下为接口指针)。

然后你可以使用:

typedef std::vector< CAdapt< CComBSTR > > MyString;
于 2012-06-19T15:08:07.917 回答
1

我认为你可以安全地做到这一点。被禁止的一件事是使用auto_ptr.

于 2012-06-19T13:53:06.360 回答
1

由于 _bstr_t 不会重载 operator& 你在 stl 容器中使用它没有问题。

于 2012-06-19T14:30:18.147 回答
0

BSTR是一个你必须调用的 C 结构SysAllocStringSysFreeString_bstr_t是一种 C++ 类型,它为你调用SysAllocString和调用,并且在. 在处理对象时,您不必也不应该调用或调用。SysFreeStringstd::vectorSysAllocStringSysFreeString_bstr_t

如果您正在处理 C 结构BSTR对象:
(1) 您可以安全地将智能指针存储在容器中,除了auto_ptr,它只是假装是智能的。
(2) Avector可以存储_bstr_t,但它不理解SysFreeString,你将不得不手动调用它。就像您必须delete使用原始指针一样,因为_bstr_t不是智能指针。
(3) astd::unique_ptr<BSTR, HRESULT (*)(BSTR)>(mybstr, SysFreeAlloc)是一个智能指针,它可以安全而神奇地为你做所有事情,包括完全安全地存储在向量中,没有开销。但是,这很难写,所以大多数人使用:

template<class T, class F>
std::unique_ptr<T, F> make_unique(T t, F f)
{return std::unique_ptr<T,F>(std::move(t), std::move(f));}

typedef decltype(make_unique(declval<BSTR>(), SysFreeAlloc)) bstr_ptr;
std::vector<bstr_ptr> container;
container.push_back(make_unique(mybstr, SysFreeAlloc));
于 2012-06-19T14:46:09.750 回答