为什么编译器使用临时变量?

时间:2014-11-26 15:54:24

标签: c++ visual-studio-2010 atl ternary-operator bstr

重现问题的最小代码:

#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。为什么要暂时?

2 个答案:

答案 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将被销毁。