I know I’m not asking this quite right, either. Please help me better form my question.
I’m having a bit of a hard time getting my mind wrapped around handles — in some ways, it looks like pointers. But unlike pointers, it seems like I can assign values directly to the handle variable, and it affects the underlying data value, not the handle itself.
The test code clearly shows that I get the same value whether I use the handle, or if I ‘dereference’ the handle to get to the data. Clearly, this wouldn’t work with unmanaged pointers. What am I not understanding?
#include <iostream> int main() { int ^y; int ^a, ^b, ^c; long x; y= gcnew int(100); a=y; b=y; c=y; c= gcnew int(200); b= 300; System::Console::WriteLine(y); // returns 100 (instead of something pointer-like) System::Console::WriteLine(*y); // also returns 100 System::Console::WriteLine(a); // 100 System::Console::WriteLine(b); // 300 System::Console::WriteLine(c); // 200 x = static_cast<long>(y); *y = 10; System::Console::WriteLine(x); // 10 System::Console::WriteLine(y); // 10 System::Console::WriteLine(*y); // 10 }
Edit to add — I suspected that WirteLine might have done the dereferencing for me, but I would have expected the static cast to long would not. Is this related to autounboxing as welll?
It’s a bit sad that C++/CLI allows this syntax. The int type is a value type, the hat is used for reference types. Your ‘y’ variable does not store an int, it stores System::Object. The compiler automatically generates a boxing instruction when you assign it. Console::WriteLine() has otherwise no problem displaying the value of an object that’s a boxed int.
The rule of thumb: use the hat when it is a class object, omit it for simple value types. Avoid the stack semantics of a reference type (omitting the hat so it automatically calls the destructor when the scope ends) until you really grok the difference between value and reference types and why Dispose() is important.