Gewusst wie: Übergabe als Verweis mit Trackingverweisen CLR-Typen
In diesem Artikel wird veranschaulicht, wie einen Nachverfolgungsverweis (%) in C++/CLI zu Übergaben-CommonLanguage Runtime (CLR)- Typen als Verweis verwendet.
So CLR-Typen als Verweis übergeben
Das folgende Beispiel veranschaulicht, wie einen Nachverfolgungsverweis verwendet, um CLR-Typen als Verweis zu übergeben.
// tracking_reference_handles.cpp
// compile with: /clr
using namespace System;
ref struct City {
private:
Int16 zip_;
public:
City (int zip) : zip_(zip) {};
property Int16 zip {
Int16 get(void) {
return zip_;
} // get
} // property
};
void passByRef (City ^% myCity) {
// cast required so this pointer in City struct is "const City"
if (myCity->zip == 20100)
Console::WriteLine("zip == 20100");
else
Console::WriteLine("zip != 20100");
}
ref class G {
public:
int i;
};
void Test(int % i) {
i++;
}
int main() {
G ^ g1 = gcnew G;
G ^% g2 = g1;
g1 -> i = 12;
Test(g2->i); // g2->i will be changed in Test2()
City ^ Milano = gcnew City(20100);
passByRef(Milano);
}
Ausgabe
Im folgenden Beispiel wird das an, das die Adresse von Trackingverweises gibt eines interior_ptr (C++/CLI) nimmt und zeigt, wie und auf Daten durch einen Nachverfolgungsverweis ändert an.
// tracking_reference_data.cpp
// compile with: /clr
using namespace System;
public ref class R {
public:
R(int i) : m_i(i) {
Console::WriteLine("ctor: R(int)");
}
int m_i;
};
class N {
public:
N(int i) : m_i (i) {
Console::WriteLine("ctor: N(int i)");
}
int m_i;
};
int main() {
R ^hr = gcnew R('r');
R ^%thr = hr;
N n('n');
N %tn = n;
// Declare interior pointers
interior_ptr<R^> iphr = &thr;
interior_ptr<N> ipn = &tn;
// Modify data through interior pointer
(*iphr)->m_i = 1; // (*iphr)->m_i == thr->m_i
ipn->m_i = 4; // ipn->m_i == tn.m_i
++thr-> m_i; // hr->m_i == thr->m_i
++tn. m_i; // n.m_i == tn.m_i
++hr-> m_i; // (*iphr)->m_i == hr->m_i
++n. m_i; // ipn->m_i == n.m_i
}
Ausgabe
Nachverfolgungsverweise und innere Zeiger
Im folgenden Codebeispiel wird gezeigt, dass Sie zwischen Trackingverweisen und inneren Zeiger konvertieren können.
// tracking_reference_interior_ptr.cpp
// compile with: /clr
using namespace System;
public ref class R {
public:
R(int i) : m_i(i) {
Console::WriteLine("ctor: R(int)");
}
int m_i;
};
class N {
public:
N(int i) : m_i(i) {
Console::WriteLine("ctor: N(int i)");
}
int m_i;
};
int main() {
R ^hr = gcnew R('r');
N n('n');
R ^%thr = hr;
N %tn = n;
// Declare interior pointers
interior_ptr<R^> iphr = &hr;
interior_ptr<N> ipn = &n;
// Modify data through interior pointer
(*iphr)->m_i = 1; // (*iphr)-> m_i == thr->m_i
ipn->m_i = 4; // ipn->m_i == tn.m_i
++thr->m_i; // hr->m_i == thr->m_i
++tn.m_i; // n.m_i == tn.m_i
++hr->m_i; // (*iphr)->m_i == hr->m_i
++n.m_i; // ipn->m_i == n.m_i
}
Ausgabe
Nachverfolgungsverweise und Werttypen
In diesem Beispiel wird durch einfaches Boxing einen Nachverfolgungsverweis auf einen Werttyp an:
// tracking_reference_valuetypes_1.cpp// compile with: /clrusing namespace System;int main() { int i = 10; int % j = i; Object ^ o = j; // j is implicitly boxed and assigned to o}
Das folgende Beispiel zeigt, dass Sie und Eingeborenverweise Nachverfolgungsverweise auf Werttypen verfügen können.
// tracking_reference_valuetypes_2.cpp
// compile with: /clr
using namespace System;
int main() {
int i = 10;
int & j = i;
int % k = j;
i++; // 11
j++; // 12
k++; // 13
Console::WriteLine(i);
Console::WriteLine(j);
Console::WriteLine(k);
}
Ausgabe
Das folgende Beispiel zeigt, dass Sie Nachverfolgungsverweise zusammen mit Werttypen und Eingeborentypen verwenden können.
// tracking_reference_valuetypes_3.cpp
// compile with: /clr
value struct G {
int i;
};
struct H {
int i;
};
int main() {
G g;
G % v = g;
v.i = 4;
System::Console::WriteLine(v.i);
System::Console::WriteLine(g.i);
H h;
H % w = h;
w.i = 5;
System::Console::WriteLine(w.i);
System::Console::WriteLine(h.i);
}
Ausgabe
Dieses Beispiel veranschaulicht, dass Sie einen Nachverfolgungsverweis auf einen Werttyp auf dem Heap der Garbage Collection erstellen können:
// tracking_reference_valuetypes_4.cpp
// compile with: /clr
using namespace System;
value struct V {
int i;
};
void Test(V^ hV) { // hv boxes another copy of original V on GC heap
Console::WriteLine("Boxed new copy V: {0}", hV->i);
}
int main() {
V v; // V on the stack
v.i = 1;
V ^hV1 = v; // v is boxed and assigned to hV1
v.i = 2;
V % trV = *hV1; // trV is bound to boxed v, the v on the gc heap.
Console::WriteLine("Original V: {0}, Tracking reference to boxed V: {1}", v.i, trV.i);
V ^hV2 = trV; // hv2 boxes another copy of boxed v on the GC heap
hV2->i = 3;
Console::WriteLine("Tracking reference to boxed V: {0}", hV2->i);
Test(trV);
v.i = 4;
V ^% trhV = hV1; // creates tracking reference to boxed type handle
Console::WriteLine("Original V: {0}, Reference to handle of originally boxed V: {1}", v.i, trhV->i);
}
Ausgabe
Vorlage funktioniert dieses nehmen ab, Verweisparameter Wert oder
Indem Sie einen Nachverfolgungsverweis in der Signatur eine Vorlagenfunktion verwenden, stellen Sie sicher, dass die Funktion mit einem Parameter, dessen Typ, handelt, CLR-Wert oder CLR-Verweis aufgerufen werden kann.
// tracking_reference_template.cpp
// compile with: /clr
using namespace System;
class Temp {
public:
// template functions
template<typename T>
static int f1(T% tt) { // works for object in any location
Console::WriteLine("T %");
return 0;
}
template<typename T>
static int f2(T& rt) { // won't work for object on the gc heap
Console::WriteLine("T &");
return 1;
}
};
// Class Defintions
ref struct R {
int i;
};
int main() {
R ^hr = gcnew R;
int i = 1;
Temp::f1(i); // ok
Temp::f1(hr->i); // ok
Temp::f2(i); // ok
// error can't track object on gc heap with a native reference
// Temp::f2(hr->i);
}
Ausgabe
Siehe auch
Referenz
Nachverfolgungsverweisoperator (Komponentenerweiterungen für C++)