重现问题的最小代码:
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
CComBSTR ccbTest( L"foo" );
const wchar_t * pTest = ccbTest ? ccbTest : L"null string";
return 0;
}
当编译器想要在CComBSTR
中存储指针时,它会使用临时pTest
。然后,它使用BSTR
类中的CCcomBSTR
转换和临时转换,并将指针存储在pTest
中。然后临时被摧毁,我在pTest
中留下一个悬空指针。
修复方法是投射CComBSTR
:
const wchar_t * pTest = ccbTest ? static_cast<BSTR>( ccbTest ) : L"null string";
我不明白为什么修复是必要的。我认为编译器只会尝试自己转换为BSTR
。为什么要暂时?
答案 0 :(得分:2)
临时存在的原因与this question相同。
如one of its answer中所述:
三元的类型?:表达式是第二类的常见类型 和第三个论点。如果两种类型相同,则会获得参考 背部。如果它们可以相互转换,那么就可以选择一个 其他人被转换[...]。既然你不能回来 对临时(转换/升级)的左值引用 变量),其类型是值类型。
由于L"null string"
是一个与CComBSTR
不同的临时类型,因此三元组的整个结果是一个值类型,这意味着结果将被临时复制。
如果您尝试:
CComBSTR ccbTest( L"foo" );
CComBSTR ccbNull( L"ull string" );
const wchar_t * pTest = ccbTest ? ccbTest : ccbNull;
没有更多的临时性。
答案 1 :(得分:0)
我在上面的示例中没有看到临时的CComBSTR。
CComBSTR是一个RAII包装类,用于帮助管理BSTR的生命周期,当它超出范围时,底层BSTR将被销毁。
ccbTest是一个自动(堆栈)变量,当它超出范围时(在_tmain的末尾),它和它管理的BSTR将被销毁。