Why does the compiler use a temporary variable?

634 views Asked by At

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?

2

There are 2 answers

0
Drax On BEST ANSWER

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.

1
Richard Critten On

I don't see a temporary CComBSTR in your above example.

CComBSTR is a RAII wrapper class used to help manage the lifetime of BSTR and when it goes out of scope the underlying BSTR will be destroyed.

ccbTest is an automatic (stack) variable and when it goes out of scope (at the end of _tmain) it and the BSTR it manages will be destroyed.