1

我相当确定我可以安全地做到:

void funcA(VARIANT &V,_variant_t &vt)
{
    vt = V;
}

但是反过来呢:

void funcB(VARIANT &V,_variant_t &vt)
{
    V = vt;
}

我在我的应用程序中看到了一些非常奇怪的行为,我将其归结为与 COM 相关的线程问题。但后来我想知道我是否错误地使用变体搞砸了内存。在 funcB 中,VARIANT V 是为 COM 调用准备的安全数组的一部分。使用我的 V=vt 行,我是否在做一个浅拷贝,当同一个变体被释放两次时会破坏事情?

我真的很喜欢 _variant_t 并避免使用所有 ::VariantXXX 方法,有没有一种巧妙的方法可以在 funcB 中使用 _variant_t 来自动复制?

4

2 回答 2

3

首先,是的,通过使用赋值运算符,funcB()您只调用浅拷贝(您可能想查看 oaidl.h 以查看VARIANT定义 - 它没有用户定义的赋值运算符,因此完成浅拷贝由编译器)。

如果您从中复制的另一个变体在您访问浅拷贝之前被清除,这会使您进入未定义的行为(例如,如果变体类型是VT_UNKNOWN指向的对象,则可以通过调用将引用计数设置为 0 后简单地销毁IUnknown::Release())。

_variant_t对您没有多大帮助,因为它没有复制到另一个对象的方法 - 请参阅 comutil.h 了解类定义 - 它仅从另一个对象复制到自身。

最简单的方法是使用VariantCopy(). 不确定当您处理它时是否会初始化安全数组。如果它是用每个元素初始化的,VT_EMPTY你可以调用VariantCopy(). 否则首先调用VariantInit()目标来初始化目标。调用VariantCopy()包含随机未初始化数据的目的地可能会导致未定义的行为。

于 2009-11-25T06:43:22.297 回答
3

如果VARIANT包含一个对象或一个对象,则在释放安全数组BSTR遇到麻烦,因为安全数组释放将释放它不拥有的资源。因此,当_variant_tsafearray 或 safearray 被销毁时,另一个将具有对已释放对象的引用。

例如,如果VARIANT包含指向您的指针,则会通过调用多次 than来IUnknown弄乱引用计数,如果它包含 a您将只复制指针而不为新变量分配新字符串。ReleaseAddRefBSTR

这就是你应该使用的原因VariantCopy,如果你想避免Variant*使用方法(出于我无法理解的原因),这可以通过_variant_t::Detach()

void funcB(VARIANT &V,_variant_t &vt)
{
    _variant_t temp = vt;
    V = temp.Detach();
    // or in one line V = _variant_t(vt).Detach(); 
}
于 2009-11-26T13:00:58.483 回答