Tracking Reference Operator (C++/CLI and C++/CX)
A tracking reference (%
) behaves like an ordinary C++ reference (&
) except that when an object is assigned to a tracking reference, the object's reference count is incremented.
All Platforms
A tracking reference has the following characteristics.
Assignment of an object to a tracking reference causes the object's reference count to be incremented.
A native reference (
&
) is the result when you dereference a*
. A tracking reference (%
) is the result when you dereference a^
. As long as you have a%
to an object, the object will stay alive in memory.The dot (
.
) member-access operator is used to access a member of the object.Tracking references are valid for value types and handles (for example
String^
).A tracking reference cannot be assigned a null or
nullptr
value. A tracking reference may be reassigned to another valid object as many times as required.A tracking reference cannot be used as a unary take-address operator.
Windows Runtime
A tracking reference behaves like a standard C++ reference, except that a % is reference-counted. The following snippet shows how to convert between % and ^ types:
Foo^ spFoo = ref new Foo();
Foo% srFoo = *spFoo;
Foo^ spFoo2 = %srFoo;
The following example shows how to pass a ^ to a function that takes a %.
ref class Foo sealed {};
// internal or private
void UseFooHelper(Foo% f)
{
auto x = %f;
}
// public method on ABI boundary
void UseFoo(Foo^ f)
{
if (f != nullptr) { UseFooHelper(*f); }
}
Common Language Runtime
In C++/CLI, you can use a tracking reference to a handle when you bind to an object of a CLR type on the garbage-collected heap.
In the CLR, the value of a tracking reference variable is updated automatically whenever the garbage collector moves the referenced object.
A tracking reference can be declared only on the stack. A tracking reference cannot be a member of a class.
It is not possible to have a native C++ reference to an object on the garbage-collected heap.
For more information about tracking references in C++/CLI, see:
Examples
The following sample for C++/CLI shows how to use a tracking reference with native and managed types.
// tracking_reference_1.cpp
// compile with: /clr
ref class MyClass {
public:
int i;
};
value struct MyStruct {
int k;
};
int main() {
MyClass ^ x = ref new 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 = ref new 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 for C++/CLI 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 = ref new array<Int32>(5);
a[0] = 21;
Console::WriteLine(a[0]);
array<int> ^% arr = a;
arr[0] = 222;
Console::WriteLine(a[0]);
}
21
222