我很确定我可以安全地做到:
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来自动复制?
答案 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}}