【问题标题】:Store BSTR in a std::vector?将 BSTR 存储在 std::vector 中?
【发布时间】:2012-06-19 13:50:13
【问题描述】:

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

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

【问题讨论】:

    标签: c++ stl vector bstr


    【解决方案1】:

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

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

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

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

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

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

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

    1. _bstr_tBSTR 的引用计数智能指针包装器,而 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;
    

    【讨论】:

      【解决方案2】:

      我认为您可以安全地执行此操作。被禁止的一件事是使用auto_ptr 的容器。

      【讨论】:

      • 但是 _bstr_t 不只是一种智能指针吗?还是特别是您不应该将 auto_ptr 放入其中?如果是这样,为什么特别是你不应该把 auto_ptr 放在那里?我确实在某个时候读过这篇文章,但我不记得为什么是现在。
      • auto_ptr 具有“奇怪”的复制语义,但 std 容器需要一些标准的复制和赋值语义。引用计数智能指针通常具有这样的语义。
      【解决方案3】:

      由于 _bstr_t 没有重载运算符&你在 stl 容器中使用它没有问题。

      【讨论】:

        【解决方案4】:

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

        如果您改为处理 C 结构 BSTR 对象:
        (1) 您可以安全地将智能指针存储在容器中,auto_ptr 除外,它只是假装是智能的。
        (2) vector 可以存储_bstr_t,除非它不理解SysFreeString,你必须手动调用它。就像您必须在原始指针上使用 delete,因为 _bstr_t 不是智能指针。
        (3) std::unique_ptr&lt;BSTR, HRESULT (*)(BSTR)&gt;(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));
        

        【讨论】:

        • @Jonnster:编辑了我的答案,我现在意识到_bstr_tBSTR 之间的区别>。
        猜你喜欢
        • 2020-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-12
        • 1970-01-01
        • 2020-05-21
        • 2015-07-01
        相关资源
        最近更新 更多