在VARIANT和_variant_t之间复制

时间:2009-11-24 17:00:58

标签: c++ visual-c++ com ole variant

我很确定我可以安全地做到:

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来自动复制?

2 个答案:

答案 0 :(得分:3)

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

如果在您访问浅副本之前清除了从中复制的其他变体,则会导致您进入未定义的行为(例如,如果变体类型为VT_UNKNOWN,则在设置引用后可能会简单地销毁指向的对象通过调用IUnknown::Release())计数到0.

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

最简单的方法是使用VariantCopy()。不确定在处理safearray时是否会初始化。如果使用VT_EMPTY的每个元素初始化它,则只需调用VariantCopy()即可。否则,首先在目标上调用VariantInit()以初始化目标。对包含随机未初始化数据的目标调用VariantCopy()可能会导致未定义的行为。

答案 1 :(得分:3)

如果VARIANT包含一个对象或BSTR,那么在您释放safearray时遇到麻烦,因为safearray deallocation将释放它不拥有的资源。因此,当_variant_t或safearray被销毁时,另一个将引用一个解除分配的对象。

例如,如果VARIANT包含指向IUnknown的指针,那么如果Release包含{AddRef,则BSTR调用VariantCopy的次数将超过Variant*。 {1}}你只需复制指针而不为新变量分配新字符串。

这就是为什么你应该使用_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(); } 方法(出于我无法理解的原因),可以使用{{1}}

{{1}}
相关问题