Prozeduren und Funktionen aufrufen (Delphi)

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Prozeduren und Funktionen - Index

Dieses Thema enthält Informationen zu folgenden Bereichen:

  • Ablaufsteuerung und Parameter in Routinen
  • Offene Array-Konstruktoren
  • Die inline-Direktive

Auflaufsteuerung und Parameter

Wenn Sie eine Prozedur oder Funktion aufrufen, wird die Steuerung vom Punkt des Aufrufs an den Rumpf der Routine übergeben. Der Aufruf kann mit dem deklarierten Namen der Routine (mit oder ohne Qualifizierer) oder mit einer prozeduralen Variablen erfolgen, die auf die Routine zeigt. In beiden Fällen müssen im Aufruf Parameter übergeben werden, die in der Reihenfolge und im Typ den in der Parameterliste der Routine angegeben Parametern entsprechen. Die an eine Routine übergebenen Parameter werden auch als tatsächliche Parameter bezeichnet - im Gegensatz zu den formalen Parametern in der Deklaration der Routine.

Beachten Sie beim Aufrufen einer Routine Folgendes:

  • Ausdrücke zur Übergabe typisierter const- und Wertparameter müssen zu den entsprechenden formalen Parametern zuweisungskompatibel sein.
  • Ausdrücke zur Übergabe von var- und out-Parametern müssen gegebenenfalls wie die entsprechenden formalen Parameter typisiert sein.
  • var- und out-Parameter können nur in zuweisungsfähigen Ausdrücken übergeben werden.
  • Wenn die formalen Parameter einer Routine nicht typisiert sind, dürfen Zahlen und echte Konstanten mit numerischen Werten nicht als tatsächliche Parameter verwendet werden.

Wenn Sie eine Routine mit Standardparameterwerten aufrufen, müssen für alle Parameter nach dem ersten akzeptierten Standardwert ebenfalls Standardwerte existieren. Aufrufe der Form SomeFunction(,,X) sind nicht zulässig.

Nimmt eine Routine Parameter entgegen, müssen Sie im Aufruf die Klammern angeben, auch wenn alle tatsächlichen Parameter Standardwerte sind. Um beim Aufruf der Prozedur

procedure DoSomething(X: Real = 1.0; I: Integer = 0; S: string = '');

alle Standardwerte zu übernehmen, geben Sie Folgendes ein:

DoSomething();
DoSomething;

Offene Array-Konstruktoren

Offene Array-Konstruktoren ermöglichen die Bildung von Arrays im Aufruf einer Funktion oder Prozedur. Sie müssen als offene Array-Parameter oder variante offene Array-Parameter übergeben werden.

Ein offener Array-Konstruktor ist wie ein Mengenkonstruktor eine Folge von Ausdrücken, die durch Kommas voneinander getrennt und in eckigen Klammern angegeben werden.

Ausgehend von den Deklarationen

var I, J: Integer;
procedure Add(A: array of Integer);

können Sie die Prozedur Add mit folgender Anweisung aufrufen:

Add([5, 7, I, I + J]);

Dieses Verfahren ist zum Folgenden äquivalent:

var Temp: array[0..3] of Integer;
  // …
  Temp[0] := 5;
  Temp[1] := 7;
  Temp[2] := I;
  Temp[3] := I + J;
  Add(Temp);

Offene Array-Konstruktoren können nur als Wert- oder const-Parameter übergeben werden. Die Ausdrücke im Konstruktor müssen zum Basistyp des Array-Parameters zuweisungskompatibel sein. Wird ein varianter offener Array-Parameter verwendet, können die Ausdrücke unterschiedliche Typen aufweisen.

Die Direktive Inline

Beim Delphi-Compiler ermöglicht zur Verbesserung der Leistung, Funktionen und Prozeduren mit der Direktive inline zu versehen. Wenn eine Funktion oder Prozedur bestimmten Kriterien entspricht, fügt der Compiler Code direkt ein anstatt einen Aufruf zu generieren. Das Ergebnis dieser Leistungsoptimierung ist schnellerer Code, der jedoch mehr Speicherplatz in Anspruch nimmt. Der Compiler produziert dabei eine größere Binärdatei. Die Direktive inline wird in Funktions- und Prozedurdeklarationen und -definitionen, genau wie andere Direktiven, verwendet.

procedure MyProc(x:Integer); inline;
begin
    // …
end;

function MyFunc(y:Char) : String; inline;
begin
  // …
end;

Die Direktive inline muss als Vorschlag an den Compiler gesehen werden. Es gibt keine Garantie, dass der Compiler eine Routine als Inline übernimmt, da bestimmte Umstände dies verhindern können. Die folgende Liste enthält die Bedingungen, unter welchen ein Inlining vorgenommen bzw. nicht vorgenommen wird.

  • Inlining wird für keinerlei spät-gebundene Methoden nicht vorgenommen. Dazu gehören virtuelle, dynamische und Botschaftsmethoden.
  • Für Routinen, die Assembler-Code enthalten, wird kein Inlining vorgenommen.
  • Für Konstruktoren und Destruktoren wird kein Inlinig vorgenommen.
  • Für den Hauptprogrammblock, die Unit-Initialisierungs- und -Finalisierungsblöcke wird kein Inlining vorgenommen.
  • Für Routinen, die vor der Verwendung nicht definiert wurden, kann kein Inlining vorgenommen werden.
  • Für Routinen, die offene Array-Parameter übernehmen, wird kein Inlining vorgenommen.
  • Für Code in Packages kann ein Inlining vorgenommen werden, Inlining über Packages-Grenzen ist jedoch nicht möglich.
  • Für Units, die zirkulär abhängig sind, wird kein Inlining vorgenommen. Dazu gehören auch indirekte, zirkuläre Abhängigkeiten, wie z.B. Unit A verwendet Unit B und Unit B verwendet Unit C, die wiederum Unit A verwendet. In diesem Beispiel wird beim Compilieren von Unit A kein Inlining von Unit B oder Unit C in Unit A vorgenommen.
  • Der Compiler kann für Code ein Inlining vornehmen, wenn eine Unit zirkulär abhängig ist, sofern der betreffende Code aus einer Unit außerhalb der zirkulären Beziehung stammt. Wenn im obigen Beispiel Unit A auch Unit D verwendet, könnte für Code aus Unit D ein Inlining vorgenommen werden, da Unit D nicht in die zirkuläre Abhängigkeit einbezogen ist.
  • Wenn eine Routine im interface-Abschnitt definiert ist, die auf im implementation-Abschnitt definierte Symbole zugreift, dann kann für diese Routine kein Inlining vorgenommen werden.
  • Wenn eine mit der Direktive inline gekennzeichnete Routine externe Symbole aus anderen Units verwendet, müssen diese Units alle in der uses-Anweisung enthalten sein, ansonsten kann kein Inlining vorgenommen werden.
  • Für Prozeduren und Funktionen, die in konditionalen Ausdrücken in while-do- und repeat-until-Anweisungen verwendet werden, kann kein Inlining vorgenommen werden.
  • In einer Unit sollte der Rumpf für eine Inline-Funktion definiert sein, bevor die Funktion aufgerufen wird. Ansonsten kann der Rumpf der Funktion, der dem Compiler bei Erreichen der Aufrufposition nicht bekannt ist, nicht als inline expandiert werden.

Wenn Sie die Implementierung von mit der Direktive inline versehenen Routinen ändern, werden alle Units, die diese Funktionen verwenden, neu compiliert. Dies ist ein Unterschied zu den herkömmlichen Regeln für das Neucompilieren, da eine Neucomplierung früher nur durch Änderungen im interface-Abschnitt einer Unit ausgelöst wurde.

Durch die {$INLINE}-Compiler-Direktive wird Ihnen eine besserer Steuerung des Inlining ermöglicht. Die Direktive {$INLINE} kann sowohl bei der Definition einer Inline-Routine als auch bei deren Aufruf eingesetzt werden. Im Folgenden finden Sie die möglichen Werte und deren Bedeutung:

Wert Bedeutung bei der Definition Bedeutung beim Aufruf

{$INLINE ON} (Vorgabe)

Die Routine wird als Kandidat für das Inlining compiliert, wenn sie mit der inline-Direktive versehen ist.

Falls möglich, wird für die Routine wird ein Inlining vorgenommen.

{$INLINE AUTO}

Verhält sich wie {$INLINE ON}; zusätzlich werden Routinen ohne die Direktive inline für das Inlining vorgesehen, wenn ihr Code weniger oder genau 32 Bytes umfasst.

{$INLINE AUTO} hat keine Auswirkungen darauf, ob für eine Routine Inlining angewendet wird, wenn es auf der Aufrufseite der Routine verwendet wird.

{$INLINE OFF}

Die Routine wird nicht als Kandidat für das Inlining vorgesehen, selbst wenn sie mit der Direktive inline gekennzeichnet ist.

Für die Routine wird kein Inlining vorgenommen.

Siehe auch