So, C++/CLI introduces a specific operator, gcnew, to allocate memory on the managed heap. This operator returns something like a pointer to the managed memory, that is called tracking handle to stress the fact that it is not a native C++ pointer, and is denotated by ^ (caret) instead of * (asterisk). Instead of NULL, the invalid value for a tracking handle is nullptr. To access members through a tracking handle is used the same arrow operator used to access members through a standard C++ pointer. Curiously enough, to dereference a tracking handle a * (asterisk) is used.
Here is piece of code that should clarify the matter:
int^ i; // 1.
if(i == nullptr)
std::cout << "i is initialized to nullptr" << std::endl;
i = gcnew int(42); // 2.
if(i != nullptr)
System::Console::WriteLine(i->GetType()); // 3.
System::Console::WriteLine(i->ToString()); // 4.
std::cout << "i has value " << *i << std::endl; // 5.
1. define a tracking handle, implicitly initialized to nullptr.
2. an int object is created on the managed heap, its tracking handle is returned, and stored in the local variable
3. the tracking handle is dereferenced to call the GetType() method. System.Int32 should be printed, since int is converted to that type on the managed memory.
4. this instruction would print the value of the int object on the managed heap, that means 42.
5. here we print the derefenced value of i, again 42.
This post is based on my reading on the book "Expert C++/CLI: .NET for Visual C++ Programmers" by Marcus Heege, APress.