4

I thought in C++/CLI declaring a local reference variable without an explicit initial value always initialized it to nullptr. I'm finding that this doesn't occur on the second and later entries into a local block. Here's the sample code.

void main()
{
    for (int i=0; i<6; i++)
    {
        switch (i)
        {
        case 2:
            Console::WriteLine("i={0} localI and hashTable no longer in scope", i);
            break;
        default:
            {
                // Declare local reference variable
                Hashtable^ hashTable;
                Int32 localI;

                Console::WriteLine("i={0} localI={1}  {2}",
                    i, localI, 
                    hashTable == nullptr ? "hashTable=nullptr" : "hashTable NOT SET to nullptr"
                                   );
                hashTable = gcnew Hashtable();
                localI = i+1;
            }
            break;
        }
    }
}

The output from this is:

i=0 localI=0  hashTable=nullptr
i=1 localI=1  hashTable NOT SET to nullptr
i=2 localI and hashTable no longer in scope
i=3 localI=2  hashTable NOT SET to nullptr
i=4 localI=4  hashTable NOT SET to nullptr
i=5 localI=5  hashTable NOT SET to nullptr

If I add explicit initialization

Hashtable^ hashTable = nullptr;
Int32 localI = 99;

Then each loop reinitializes the reference and localI

i=0 localI=99  hashTable=nullptr
i=1 localI=99  hashTable=nullptr
i=2 localI and hashTable no longer in scope
i=3 localI=99  hashTable=nullptr
i=4 localI=99  hashTable=nullptr
i=5 localI=99  hashTable=nullptr

This seems to contradict what I found here on MSDN which says:

"The following code example shows that when handles are declared and not explicitly initialized, they are default initialized to nullptr."

JonN
  • 2,498
  • 5
  • 33
  • 49

1 Answers1

4

This is by design, the CLR only initializes local variables on method entry. Scope blocks inside a method are a language implementation detail that disappears after compilation. Other managed languages are alike, VB.NET behaves the exact same way. C# would too, but doesn't permit this kind of code due to its definite assignment rule.

This behavior otherwise simplifies the runtime implementation greatly. The jitter simply generates code to blast the stackframe to zero at entry.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thanks, that makes sense. So the MSDN reference would more accurate to say **"All default initialization only occurs once at the start of a method and not within local scope blocks."** I was misled by C++/CLI advertizing default initialization without mentioning the exceptions. It would be more robust to have the rules on using uninitialized variables match C#. I'm not sure what allowing use of uninitialized handles buys me in C++/CLI beyond more debugging practice. Thanks @Hans I appreciate your vast knowledge. – JonN Jan 19 '13 at 22:25