将BSTR存储在std :: vector中?

时间:2012-06-19 13:50:14

标签: c++ stl vector bstr

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

我一直在寻找一种更简单/更清洁的解决方案,并考虑将矢量声明为矢量< _bstr_t>其中包括自动清理。然而,在我的脑海中,有些事情是在标准容器中保存有效的智能指针时引发警报。我的担忧是否合理,或者我可以安全地做到这一点吗?如果没有,还有其他更好的解决方案吗?

4 个答案:

答案 0 :(得分:3)

  

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

是。虽然可以安全地使用_bstr_t,但请注意,它不仅是智能指针,而且是引用计数智能指针。这意味着额外的费用。

  

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

我通常使用CComBSTR代替BSTR_bstr_t。如果您需要引用计数,那么您必须回到_bstr_t。例如:如果你也在使用ATL,你可能只需要CComBSTR s。

  

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

     

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

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

  1. _bstr_tBSTR上的引用计数智能指针包装器,而CComBSTR 提供任何引用计数。
  2. _bstr_t 重新定义地址操作符,因此可以安全地存储在STL容器中。使用CComBSTR,您需要使用CAdapt
  3. 关于CAdapt对象:

      

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

    然后你可以使用:

    typedef std::vector< CAdapt< CComBSTR > > MyString;
    

答案 1 :(得分:1)

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

答案 2 :(得分:1)

由于_bstr_t不会使运算符&amp;在stl容器中使用它没有问题。

答案 3 :(得分:0)

BSTR是一个C结构,您必须调用SysAllocStringSysFreeString_bstr_t是一种C ++类型,可以为您调用SysAllocStringSysFreeString,并且在std::vector中完全100%安全。在处理SysAllocString个对象时,您不必也不应该致电SysFreeString_bstr_t

如果您正在处理C结构BSTR对象:
(1)您可以安全地将智能指针存储在容器中,auto_ptr除外,它只是假装聪明。
(2)vector可以存储_bstr_t,但不理解SysFreeString,您必须手动调用它。就像你必须在原始指针上delete一样,因为_bstr_t 不是智能指针。
(3)std::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));
相关问题