Search code examples
c++visual-studio-2010atlternary-operatorbstr

Why does the compiler use a temporary variable?


Minimal code reproducing the problem:

#include "stdafx.h"


int _tmain(int argc, _TCHAR* argv[])
{
    CComBSTR ccbTest( L"foo" );
    const wchar_t * pTest = ccbTest ? ccbTest : L"null string";

    return 0;
}

The compiler uses a temporary CComBSTR when it wants to store a pointer in pTest. It then uses the BSTR conversion available in the CCcomBSTR class, with the temporary, and stores the pointer in pTest. Then the temporary is destroyed, and I am left with a dangling pointer in pTest.

The fix is to cast the CComBSTR:

const wchar_t * pTest = ccbTest ? static_cast<BSTR>( ccbTest ) : L"null string";

I don't understand why the fix is necessary. I thought that the compiler would just try to convert to BSTR all by itself. Why a temporary?


Solution

  • The temporary exist for the same reasons this question does.

    And as stated in one of its answer:

    The type of the ternary ?: expression is the common type of its second and third argument. If both types are the same, you get a reference back. If they are convertable to each other, one gets chosen and the other gets converted [...]. Since you can't return an lvalue reference to a temporary (the converted / promoted variable), its type is a value type.

    Since your L"null string" is a temporary of a different type than CComBSTR the whole result of the ternary is a value type which means the result is copied in a temporary.

    If you try:

    CComBSTR ccbTest( L"foo" );
    CComBSTR ccbNull( L"ull string" );
    
    const wchar_t * pTest = ccbTest ? ccbTest : ccbNull;
    

    There is no more temporary.