Verfolgungsreferenz in C ++ / CLI

7

Kann mir bitte jemand das folgende Code-Snippet erklären?

%Vor%

Und meine zweite Frage ist: Gibt es irgendeinen Grund, so etwas zu haben?:

%Vor%

Mehr noch: Ich sehe keinen Unterschied zwischen Werttyp und ref-Typ, da auf beide vom Handler gezeigt werden kann (

    
Marc Andreson 01.08.2010, 00:40
quelle

1 Antwort

24

Denken Sie daran, dass die primäre Verwendung von C ++ / CLI zum Entwickeln von Klassenbibliotheken für die Verwendung durch GUIs / Webdienste, die in anderen .NET-Sprachen erstellt wurden, dient. Daher muss C ++ / CLI sowohl Referenz- als auch Werttypen unterstützen, da andere .NET-Sprachen dies tun.

Darüber hinaus kann C # ref -Parameter haben, die ebenfalls typisiert sind. Dies ist nicht eindeutig für C ++ / CLI und macht Werttypen in keiner Weise äquivalent zu Referenztypen.

Um die Fragen in Ihren Code-Kommentaren zu beantworten:

  

Erstelle ich eine Kopie oder was?

Ja, SetValueTwo nimmt seinen Parameter nach Wert, so dass eine Kopie erstellt wird.

  

ist diese Kopie wegwerfbar, obwohl Werttypen keine Destruktoren haben?

Falsch. Werttypen können Destruktoren haben. Werttypen können keine Finalizer haben. Da dieser spezielle Werttyp einen trivialen Destruktor hat, wird der C ++ / CLI-Compiler nicht IDisposable implementieren. Wenn ein Parameter ein IDisposable-Werttyp ist, stellt der C ++ / CLI-Compiler in jedem Fall sicher, dass Dispose aufgerufen wird, wenn die Variable den Gültigkeitsbereich verlässt, genau wie Stapel-Semantik für lokale Variablen. Dies schließt eine abnormale Beendigung (ausgelöste Ausnahme) ein und erlaubt die Verwendung von verwalteten Typen mit RAII.

Beide

%Vor%

und

%Vor%

sind erlaubt und setzen eine Boxed-Value-Type-Instanz auf den verwalteten Heap (der überhaupt kein Heap ist, sondern ein Stack, aber es sind nicht die Call-Stacks, in denen lokale Variablen gespeichert sind, so dass Microsoft sie aufruft) ein Heap wie der native Speicherbereich für die dynamische Zuweisung).

Im Gegensatz zu C # kann C ++ / CLI getippte Handle für Box-Objekte behalten.

Wenn eine Verfolgungsreferenz auf eine Werttypinstanz im Stapel oder in ein anderes Objekt eingebettet ist, muss der Inhalt des Werttyps bei der Bildung der Referenz eingerahmt werden.

Tracking-Referenzen können auch mit Referenztypen verwendet werden, und die Syntax zum Abrufen eines Handles ist dieselbe:

%Vor%

Eine Sache, an die ich mich nie vollständig erinnern kann, ist, dass die Syntax im Vergleich zu nativem C ++ nicht 100% ig konsistent ist.

Deklarieren Sie eine Referenz:

%Vor%

Deklarieren Sie einen Zeiger:

%Vor%

Bilden Sie einen Zeiger:

%Vor%

Beachten Sie, dass der unäre Adreßoperator mit der Referenznotation in C ++ und C ++ / CLI übereinstimmt. Dies scheint zu widersprechen eine Tracking-Referenz kann nicht als unärer Take-Address-Operator (MSDN) verwendet werden auf die ich gleich zurück komme.

Zuerst aber die Inkonsistenz:

Bilden Sie eine Referenz von einem Zeiger:

%Vor%

Beachten Sie, dass der unäre Dereferenzoperator immer * ist. Es ist dasselbe wie die Zeiger-Notation nur in der natürlichen Welt, die der Adresse völlig entgegengesetzt ist - von denen, wie oben erwähnt, immer dasselbe Symbol wie die Referenznotation ist.

Kompilierbares Beispiel:

%Vor%

Nun zur unären Adresse von:

Erstens ist der MSDN-Artikel falsch, wenn er sagt:

  

Das folgende Beispiel zeigt, dass eine Verfolgungsreferenz nicht als unärer Take-Adress-Operator verwendet werden kann.

Die korrekte Aussage lautet:

% ist der Address-of-Operator für die Erstellung eines Tracking-Handles. Seine Verwendung ist jedoch wie folgt begrenzt:

Ein Tracking-Handle muss auf ein Objekt im verwalteten Heap zeigen. Referenztypen sind immer auf dem verwalteten Heap vorhanden, sodass kein Problem auftritt. Werttypen und native Typen können sich jedoch im Stapel (für lokale Variablen) oder in einem anderen Objekt (Elementvariablen des Werttyps) befinden. Versuche, ein Tracking-Handle zu erstellen, bilden ein Handle für eine umrahmte Kopie der Variablen: Das Handle ist nicht mit der ursprünglichen Variablen verknüpft. Als Konsequenz des Boxing-Prozesses, der Metadaten benötigt, die für native Typen nicht existieren, ist es nie möglich, ein Tracking-Handle für eine Instanz eines nativen Typs zu haben.

Beispielcode:

%Vor%

Wenn System::Int32 kein Werttyp ist, dann weiß ich nicht was ist. Versuchen wir System::DateTime , was ein nicht primitiver Werttyp ist:

%Vor%

Das funktioniert!

Als weitere unglückliche Einschränkung werden primitive Typen mit doppelter Identität (z. B. native int und verwalteter Werttyp System::Int32 ) nicht korrekt behandelt, der Operator % (Formularverfolgungsreferenz) kann nicht boxen auch wenn der .NET-Name für den Typ angegeben ist .

    
Ben Voigt 01.08.2010, 02:05
quelle

Tags und Links