% (Tracking Reference)
A tracking reference is similar to a C++ reference, to specify that a variable is passed to a function by reference and to create an alternative name for an object. However, the object referenced by a tracking reference can be moved during execution by the common language runtime garbage collector. For more information on C++ references, see References (C++).
Remarks
A tracking reference is updated by the garbage-collected heap in much the same way that a handle to a reference is updated, when the object moves on the garbage-collected heap.
Use a tracking reference to bind to an object that could possibly be on the garbage-collected heap. Use a tracking reference to a handle when binding to an object of a CLR type on the garbage-collected heap.
It is not possible to have a native C++ reference to an object on the garbage-collected heap.
A tracking reference can point to a whole object, data member, or storage location.
A tracking reference can only be declared on the stack. A tracking reference cannot be a member of a class.
Tracking references are valid to value types and handles.
You can have references to native types and native pointers.
When a tracking reference is initialized, it performs the equivalent of a shallow copy, a "pointer" to shared memory, which is the same behavior as when you initialize a native reference. Also like a native reference, when you assign to a tracking reference, a deep copy is performed, meaning that the memory location of the value is changed.
A tracking reference cannot be assigned null. A tracking reference is rebindable, meaning that you can initialize a tracking reference multiple times.
For more information about tracking references, see:
How to: Pass CLR Types by Reference with Tracking References Tracking References and Interior Pointers
How to: Use Tracking References and Value Types Tracking References and Unary "Take-Address" Operator
How to: Cannot Use Tracking References and Unary "Take-Address" Operator
How to: Write Template Functions that Take Native, Value, or Reference Parameters
Example
// tracking_reference_1.cpp
// compile with: /clr
ref class MyClass {
public:
int i;
};
value struct MyStruct {
int k;
};
int main() {
MyClass ^ x = gcnew MyClass;
MyClass ^% y = x; // tracking reference handle to reference object
int %ti = x->i; // tracking reference to member of reference type
int j = 0;
int %tj = j; // tracking reference to object on the stack
int * pi = new int[2];
int % ti2 = pi[0]; // tracking reference to object on native heap
int *% tpi = pi; // tracking reference to native pointer
MyStruct ^ x2 = gcnew MyStruct;
MyStruct ^% y2 = x2; // tracking reference to value object
MyStruct z;
int %tk = z.k; // tracking reference to member of value type
delete[] pi;
}
The following sample shows how to bind a tracking reference to an array.
// tracking_reference_2.cpp
// compile with: /clr
using namespace System;
int main() {
array<int> ^ a = gcnew array< Int32 >(5);
a[0] = 21;
Console::WriteLine(a[0]);
array<int> ^% arr = a;
arr[0] = 222;
Console::WriteLine(a[0]);
}
Output
21 222