Delphi übergibt Parameter als Referenz oder als Wert / Kopie

7

Kontext 1

%Vor%

Kontext2

%Vor%

myFunc für Context2 wurde von Context1 aufgerufen, die lokale Variable mytext verweist auf einen Speicher außerhalb von Context2? oder die mytext haben ihren eigenen Speicherplatz im Bereich und werden mit dem gleichen Inhalt von text ? Ich vermisse wahrscheinlich etwas wirklich Grundlegendes, weil ich einen access violation Fehler erhalte.

Es gibt eine Möglichkeit, explizit anzugeben, ob eine Funktion Parameter per Referenz oder nach Wert erhalten soll und dann wie in C kopiert wird. Ich bin mir nicht sicher, wie ich es mache.

    
Vitim.us 03.03.2012, 04:33
quelle

3 Antworten

20

Das Speichermanagement für Delphi-Strings ist etwas ungewöhnlich. Nachdem Sie myFunc(text) aufgerufen und textcopy := mytext zugewiesen haben, zeigen alle drei Variablen ( text , mytext und textcopy ) auf dieselbe Adresse, die ursprüngliche Zeichenfolge.

Aber Sobald Sie eine dieser Variablen verwenden, um Änderungen an der Zeichenfolge vorzunehmen, klont Delphi die Zeichenfolge hinter den Kulissen und Ihre Änderungen werden auf die Kopie angewendet. Die anderen beiden Variablen zeigen immer noch auf das Original, also bleiben sie unverändert. Daher werden alle Änderungen, die in Kontext 2 vorgenommen wurden, nicht in Kontext 1 gesehen - diese "Kopie-auf-schreiben" -Mechanik gibt Ihnen effektiv eine semantische Übergabe nach Wert. Alle diese Zeichenfolgen sind Referenzzähler und werden automatisch freigegeben, sobald alle Referenzen den Gültigkeitsbereich verlassen.

Es gibt jedoch eine Ausnahme. Wenn Sie auf die Zeichenfolge mithilfe von Zeigern statt auf Zeichenfolgen zugreifen, umgehen Sie den Kopierschritt und Ihre Änderungen wirken sich auf das Original aus. Sie werden auch die Referenzzähllogik umgehen und möglicherweise mit einem Zeiger auf einen nicht zugeordneten Speicherblock enden. Dies könnte der Grund für Ihre Zugriffsverletzung sein, aber ich könnte nicht ohne weitere Details / mehr Code sagen.

Wenn Sie eine Referenzübergabe wünschen, deklarieren Sie Ihre Funktion als myFunc(var mytext: String) . Wenn Sie Delphi zwingen möchten, die Zeichenfolge zu kopieren, anstatt zu warten, bis sie geändert wurde, können Sie System.UniqueString .

    
Nick Barnes 03.03.2012, 05:40
quelle
9

In String ist string ein Referenztyp, der normalerweise wie ein Werttyp funktioniert. Es ist auf dem Heap (nicht dem Stapel wie die meisten Werttypen) zugeordnet und verfügt über eine automatische Referenzzählung und eine Semantik zum Kopieren und Schreiben.

Um zu verstehen, was dies bedeutet, überlegen Sie, wie normale Werttypen, z.B. ein Integer, verhält sich, wenn es als Parameter an eine Prozedur übergeben wird:

%Vor%

Der var-Parameter in PassByReferenceInOut entspricht der C-Konvention, einen Zeiger auf das Argument zu übergeben.

Dieselbe Semantik gilt für die Übergabe von Zeichenfolgenparametern, aber es gibt einen feinen Unterschied in der internen Darstellung der Werte:

%Vor%

Wenn Sie sicherstellen möchten, dass eine Prozedur auf ihrer eigenen Kopie des Zeichenfolgenwerts ausgeführt wird, verwenden Sie die UniqueString-Prozedur, z. B .:

%Vor%     
Henrick Hellström 03.03.2012 12:27
quelle
6

In Delphi fügen Sie explizit das Schlüsselwort var hinzu:

%Vor%

Das bedeutet, dass myFunc den Inhalt der Zeichenfolge ändern kann und der Aufrufer die Änderungen sehen kann.

    
Mike W 03.03.2012 05:31
quelle