Modern C++ programs should almost always use vectors and iteriators in preference to the lower-level arrays and pointers, and strings to replace C-style array based character strings. Well designed programs use arrays and pointers only in the internals of class implementations where speed is essential. As well as being less powerful, C-style strings are the root cause of many many security problems.
In CLI instead of using pointers you use use tracking handles. Tracking handles are very similar to pointers but they behave differently since they refer to managed objects, not native objects. They are delibertly implemented differently to clearly differentiate them from standard C++ pointers (which of course you can still use). Whether a type is native or managed depends on wether it is declared with C++ syntax or with the C++/CLI syntax for managed types, and both can be used in the same project.
There are 2 heaps in a C++/CLI application, the native heap and the managed heap. The native heap is used when you use the new statement and you must explicitally manage the lifetime of objects on it yourself. The managed heap is a seperate pool of memory that is managed by the garbage collector. Instead of a normal pointer into the native heap you use a tracking handle to to point to objects in the managed heap and it is expressed usign the ^ symbol instead of *. The reason these new pointer like entities are called trackigng handles is that the garbage colletor also moves around objects in memory to keep the heap efficient. This means that unlike a native pointer a tracking handles address may change during execution, so you don't normally access the address of a handle.
Therefore, native C++ = vectors or pointers, C++/CLI = handles.
Doing Pointer Type Things In C++/CLI
int count; count = 0; sendBytes[count++] = 'A'; sendBytes[count++] = 'B'; sendBytes[count++] = 'C';
Handles ^ (Use reference to pass back of values)
Note that handles are typically used to pass classes and when used work in much the same way as an old C pointer.
Member selection through a handle (^) uses the pointer-to-member operator (->).
To pass a handle to a function
void SomeFunction(int channelsCount, array<unsigned int>^MyData)
To call the function
array<unsigned int>^ MyData = gcnew array<unsigned int>(512); artNetOutput1->TxArtDmxPacket(160, MyData);
However if you do this with a variable, then the original value doesn't get updated. The issue here is that when you box a value-type (which is what happens when you pass a handle the runtime creates a copy of your value-type on the GC heap: so any modifications to this copy are not reflected in the orginial instance of the value-type. Instead, for variable you need to use a reference.
Using with strings
String ^our_sentance = L”Hellow world”; //The ‘^’ is the handler character array<String^> ^ports; String ^port; String ^PasswordEncrypt::EncryptString(String ^password)
If you want to pass a memory location to a function and have the function modify it (i.e. pass a class that can be modified by a function or pass a variable as part of the function arguments that can be used to return values in) you need to use a reference. In C++\cli you use the % character for a tracking reference, which means a reference to a managed location.
To pass a reference to a function:
void MMTimer::GetResolution (UInt32 %minimum, UInt32 %maximum, String ^%name, MyClass ^%Class1)
To call the function
UInt32 max; UInt32 min; String ^theName; MyClass ^theClass; MySendTimer->GetResolution(min, max, theName, theClass);
You use handle and a reference say in a function definition (e.g. for strings and classes):
Updating a class to a new class
If you pass a class handle to another class, say as ^% arguments in its constructor, the contents of the class can be modified at any time by the called class. This is because you store the handle to the classes location in managed memory and then when you modify a component of the class you are modifying that original location in memory.
However, say you want to modify a passed class by re-creating it, for instance to re-create it as a different size if it contains arrays. You can call a function and have it do this using ^% but it only works if the actual function you call re-assigns the handle to the newly created class. This is because the function has the ^%MyClass in its arguments so it knows to change the handle when you use MyClass = MyNewlyCreatedClass;
However you can't store the handle to a global handle and then do this later on in some other independant function, as if you use MyClass = MyNewlyCreatedClass; you are just updating the local handle MyClass, not refering back to the original handle. In this instance you can instead use a delegate. With a delegate you can pass a pointer to a function in another class and then when that other class has modified the class and wants to update the original class, it can call the passed function with the new handle as an argument, which the original class can then use to update its original handle. See delegates for an example…
Pointer to a function
A callback function is a pointer to a function – see delegates
Alternatively if you want to create a way for the user of a class to have one of their own functions called, use an event.