Sie haben bis jetzt viele gute Antworten gegeben worden, aber beginnend mit der Antwort, die Sie bereits mit Zeigern zu tun haben, wenn Sie lange Strings verwenden, dynamische Arrays und Objektreferenzen sollten Sie beginnen sich fragen, warum Sie würde Einsatz Zeiger anstelle von langen Strings, dynamischen Arrays und Objektreferenzen. Gibt es einen Grund, immer noch Zeiger zu benutzen, da Delphi sie in vielen Fällen gut versteckt?
Lassen Sie mich Ihnen zwei Beispiele für die Verwendung von Pointer in Delphi geben. Sie werden sehen, dass dies für Sie wahrscheinlich überhaupt nicht relevant ist, wenn Sie hauptsächlich Business-Apps schreiben. Es kann jedoch wichtig werden, wenn Sie jemals Windows- oder API-Funktionen von Drittanbietern verwenden müssen, die von keiner der Standard-Delphi-Einheiten importiert werden und für die keine Importeinheiten in (beispielsweise) den JEDI-Bibliotheken gefunden werden. Und es kann der Schlüssel sein, um das notwendige letzte Stück Geschwindigkeit in dem Code zur Verarbeitung von Strings zu erreichen.
Pointers können verwendet werden, mit Datentypen in unterschiedlichen Größen (unbekannt bei der Kompilierung) beschäftigen
den Bitmap-Datentyp Windows-Betrachten. Jedes Bild kann unterschiedliche Breite und Höhe haben, und es gibt verschiedene Formate, die von Schwarz und Weiß (1 Bit pro Pixel) über 2^4, 2^8, 2^16, 2^24 oder sogar 2^32 Grauwerte oder Farben reichen . Das bedeutet, dass zur Kompilierungszeit nicht bekannt ist, wie viel Speicher eine Bitmap belegen wird.
In Windows.pas gibt es die TBitmapInfo Typ:
type
PBitmapInfo = ^TBitmapInfo;
tagBITMAPINFO = packed record
bmiHeader: TBitmapInfoHeader;
bmiColors: array[0..0] of TRGBQuad;
end;
TBitmapInfo = tagBITMAPINFO;
Das TRGBQuad Element ein einzelnes Pixel beschreibt, aber die Bitmap hat natürlich mehr als ein Pixel enthalten.Daher würde man nie eine lokale Variable vom Typ TBitmapInfo, aber immer einen Zeiger darauf verwenden:
var
BmpInfo: PBitmapInfo;
begin
// some other code determines width and height...
...
BmpInfo := AllocMem(SizeOf(TBitmapInfoHeader)
+ BmpWidth * BmpHeight * SizeOf(TRGBQuad));
...
end;
nun den Zeiger verwenden, können Sie alle Pixel zuzugreifen, obwohl TBitmapInfo nur ein einziges hat. Beachten Sie, dass Sie für einen solchen Code die Bereichsprüfung deaktivieren müssen.
Stuff wie das kann natürlich auch mit der TMemoryStream Klasse behandelt werden, die im Grunde eine freundliche Wrapper um einen Zeiger auf einen Speicherblock ist.
Und natürlich ist es viel einfacher, einfach ein TBitmap zu erstellen und seine Breite, Höhe und Pixelformat zuzuweisen. Um dies erneut zu sagen, eliminiert die Delphi-VCL die meisten Fälle, in denen Zeiger sonst notwendig wären.
Zeiger auf Zeichen verwendet werden String-Operationen zu beschleunigen
Dies ist, wie die meisten Mikro-Optimierungen, verwendet werden, etwas, das nur in extremen Fällen, nachdem Sie profiliert haben und fand den Code Strings zu konsumieren viel Zeit.
Eine nette Eigenschaft von Strings ist, dass sie als Referenz gezählt werden. Das Kopieren kopiert nicht den Speicher, den sie belegen, sondern erhöht nur den Referenzzähler. Nur wenn der Code versucht, eine Zeichenfolge zu ändern, deren Referenzzahl größer als 1 ist, wird der Speicher kopiert, um eine Zeichenfolge mit einer Referenzzählung von 1 zu erstellen, die dann sicher geändert werden kann.
Eine nicht so nette Eigenschaft von Strings ist, dass sie als Referenz gezählt werden. Jede Operation, die möglicherweise die Zeichenfolge ändern könnte, muss sicherstellen, dass die Referenzanzahl 1 ist, da andernfalls Änderungen an der Zeichenfolge gefährlich wären. Das Ersetzen eines Zeichens in einer Zeichenfolge ist eine solche Änderung. Um sicherzustellen, dass die Referenzzählung 1 ist, wird ein Aufruf an UniqueString() vom Compiler hinzugefügt, wenn ein Zeichen in einer Zeichenfolge geschrieben wird. Jetzt schreibt n Zeichen einer Zeichenkette in einer Schleife verursacht Unique()-n mal aufgerufen werden, auch wenn nach dem ersten Mal ist sichergestellt, dass der Referenzzähler 1. Das bedeutet im Wesentlichen n - 1 Aufrufe von UniqueString() werden unnötigerweise ausgeführt.
Die Verwendung eines Zeigers auf die Zeichen ist eine gängige Methode, um Zeichenfolgenoperationen zu beschleunigen, die Schleifen enthalten. Stellen Sie sich vor, Sie möchten (für Anzeigezwecke) alle Leerzeichen in einer Zeichenfolge durch einen kleinen Punkt ersetzen. Verwenden Sie die CPU Ansicht des Debuggers und vergleicht den Code für diesen Code ausgeführt
procedure MakeSpacesVisible(const AValue: AnsiString): AnsiString;
var
i: integer;
begin
Result := AValue;
for i := 1 to Length(Result) do begin
if Result[i] = ' ' then
Result[i] := $B7;
end;
end;
mit diesem Code
procedure MakeSpacesVisible(const AValue: AnsiString): AnsiString;
var
P: PAnsiChar;
begin
Result := AValue;
P := PAnsiChar(Result);
while P[0] <> #0 do begin
if P[0] = ' ' then
P[0] := $B7;
Inc(P);
end;
end;
In der zweiten Funktion wird es nur ein Anruf zu Unique(), wenn Die Adresse des ersten Zeichens wird dem Char-Zeiger zugewiesen.
Hoffe, das ist genug Informationen, ich kann mehr hinzufügen, wenn Sie möchten. –
+1 Hervorragende Erklärung. Gute Arbeit! –
Danke, ich helfe gerne. Aber es ist immer schön, wenn es geschätzt wird. –