Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Funktionsrückgabewert: Array (https://www.delphipraxis.net/121246-funktionsrueckgabewert-array.html)

violinenspieler1000 24. Sep 2008 14:59


Funktionsrückgabewert: Array
 
Hallo,

ich möchte eine Funktion schreiben, die mir als Rückgabewert ein (mehrdimensionales) Array liefert.

Geht sowas? Wie kann man das relaisieren?


Thomas

DeddyH 24. Sep 2008 15:01

Re: Funktionsrückgabewert: Array
 
Das müsste gehen, wenn Du das Array als Typ deklarierst und die Funktion dann diesen Typ zurückgibt.

DP-Maintenance 24. Sep 2008 17:20

DP-Maintenance
 
Dieses Thema wurde von "Jelly" von "Klatsch und Tratsch" nach "Object-Pascal / Delphi-Language" verschoben.
Klatsch & Tratsch ist das aber noch nicht :-)

SirThornberry 24. Sep 2008 17:44

Re: Funktionsrückgabewert: Array
 
Zitat:

Zitat von violinenspieler1000
...Geht sowas?...

Was spricht dagegen es einfach zu probieren? :gruebel:

sx2008 25. Sep 2008 04:15

Re: Funktionsrückgabewert: Array
 
Zitat:

Zitat von violinenspieler1000
ich möchte eine Funktion schreiben, die mir als Rückgabewert ein (mehrdimensionales) Array liefert.

Kannst du mal dein ursprüngliches Problem schildern?
Es ist günstig, mehrdimensionales Arrays in einer Klasse zu verpacken.
Das hat den Vorteil, dass du alle Funktionen, die sich auf das Array beziehen in der Klasse unterbringen kannst.
Insbesondere Sparse-Arrays lassen sich nur mit Klassen sinnvoll implementieren.
Genaueres kann man aber erst sagen, wenn man weiss, was du vorhast.

oki 25. Sep 2008 07:38

Re: Funktionsrückgabewert: Array
 
Moin,

bei der Übergabe in Funktionen/Proceduren werden Arrays angegeben wie dynamische Arrays. Dabei sollte es egal sein, ob ein- oder mehrdimensional.
Delphi-Quellcode:
Procedure SetArr(Value : Array of Integer);
Die Methode mit der Typdeklaration wurde ja schon benannt.
Delphi-Quellcode:
type
  TDeclArray = Array [0..Max] of Integer;

Procedure SetArr(Value : TDeclArray);
Im ersten Fall kannst Arrays beliebiger Länge übergeben, im Zweiten nur vom deklarierten Typ.
Achte bei dem Hinweis für die Klassen darauf, dass du Arrays nicht im published-Teil als Typ angegen kannst.

Gruß oki

edit: Sorry, imho gilt das natürlich auch für Rückgabewerte von Funktionen. Im Fall Published sind natürlich propertys gemeint.

Roachford 25. Sep 2008 13:56

Re: Funktionsrückgabewert: Array
 
Dynamische Arrays als Rückgabewert sind programmiertechnisch mehr als ineffizient, da der Rückgabewert immer kopiert wird. Es lohnt sich somit definitiv nicht, wenn dann eher als VAR Parameter übergeben und dann in der Funktion füllen.

ABER: dynamische Arrays etc. sind nur noch an wenigen Stellen sinnvoll einsetzbar, da die Nachteile überwiegen:

Vorteile:
- Member sind vom direkten Typ

Nachteile:
- man muss genau sein beim Handling, vor allem bei Übergaben, da es sonst leicht und viel kopiert wird von Delphi und somit der Speicherverbrauch steigt
- Erhöhter Aufwand beim entfernen einzelner Member
- Man explizit drauf achten by reference Übergaben zu deklarieren, damit man das Array in Funktionen ändern kann, ansonsten arbeitet man auf einer Kopie

TList und deren Derivate ersetzen die dynamischen Arrays mit einer z.T. effizienteren Verwaltung (löschen eines Elementes schiebt in TList nur die Zeiger, in einem Array Of müssen die Elemente, also der Inhalt, bewegt werden, was meist ungemein grösser ist)

oki 25. Sep 2008 14:03

Re: Funktionsrückgabewert: Array
 
Hi,

da ich mir jetzt nicht sicher bin formuliere ich es mal als Aussage und Frage.

Dynamische Arrays sind imho Zeiger auf Speicherbereiche. Das Setzen einer Variable auf nil die ein dynamisches Array hält reicht aus um das Array zu "lösche".
Somit sollte eine Übergabe eines dyn. Arrays in einer Procedure doch die Übergabe eines Zeigers sein. Ist dann überhaupt eine Deklaration als var-Parameter notwendig?

Das es bei der Übergabe von dyn. Arrays in Procedure und Funktionen zum delphiinternen kopieren kommt ist mir so neu. Zur Not habe ich wieder was dazu gelernt.

Gruß oki

Roachford 25. Sep 2008 14:42

Re: Funktionsrückgabewert: Array
 
Zitat:

Zitat von oki
Dynamische Arrays sind imho Zeiger auf Speicherbereiche.

Korrekt.

Zitat:

Zitat von oki
Das Setzen einer Variable auf nil die ein dynamisches Array hält reicht aus um das Array zu "lösche".

Dabei greift hier Compilermagic von Delphi, welche implizit ein SetLength(x, 0) damit aufruft und zuvor, wenn nötig, das Array finalisiert.

Zitat:

Zitat von oki
Somit sollte eine Übergabe eines dyn. Arrays in einer Procedure doch die Übergabe eines Zeigers sein. Ist dann überhaupt eine Deklaration als var-Parameter notwendig?

Wenn du var weglässt, erstellt dir Delphi vor Änderungen eine Kopie des Arrays und somit setzt du höchstens die Kopie auf 0.

Mit dem var hingegen legt Delphi dir keine Kopie an sondern übergibt dir den originalen Zeiger auf das Array vom Aufrufer. Somit kannst du das Array auch verändern.

Zitat:

Zitat von oki
Das es bei der Übergabe von dyn. Arrays in Procedure und Funktionen zum delphiinternen kopieren kommt ist mir so neu. Zur Not habe ich wieder was dazu gelernt.

Ich müsste hier vllt. nochmal explizit darauf hinweisen, dass ich die Veränderung des Arrays meine - also von NIL setzen bist SetLength(). Ein Veränderung der Arrayinhalte ohne Grössenänderung ist natürlich ohne var möglich, da er die Daten an der Stelle direkt editiert, welche der Zeiger bestimmt.

Delphi-Quellcode:
program ArrayTest;

{$APPTYPE CONSOLE}

uses
  Types,
  SysUtils;

procedure ChangeContent(AList: TIntegerDynArray);
var
  i: integer;
begin
  for i := low(AList) to high(AList) do
    AList[i] := 10 - i;
end;

procedure ChangeArray(AList: TIntegerDynArray);
var
  i: integer;
begin
  SetLength(AList, 4);
  for i := low(AList) to high(AList) do
    AList[i] := 50 + i;
end;

procedure Test;
var
  lTestCaller: TIntegerDynArray;
  lInt, i: integer;
begin
  SetLength(lTestCaller, 3);

  for i := low(lTestCaller) to high(lTestCaller) do
    lTestCaller[i] := Succ(i);

  WriteLn('content prior ChangeContent():');
  for lInt in lTestCaller do
    WriteLn(lInt);
  WriteLn;

  ChangeContent(lTestCaller);

  WriteLn('content after ChangeContent() & prior ChangeArray():');
  for lInt in lTestCaller do
    WriteLn(lInt);
  WriteLn;

  ChangeArray(lTestCaller);

  WriteLn('content after ChangeArray():');
  for lInt in lTestCaller do
    WriteLn(lInt);
end;

begin
  try
    Test;

    ReadLn;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.
Ausgabe:
Zitat:

Zitat von Command Console
content prior ChangeContent():
1
2
3

content after ChangeContent() & prior ChangeArray():
10
9
8

content after ChangeArray():
10
9
8


oki 25. Sep 2008 14:53

Re: Funktionsrückgabewert: Array
 
ok,

somit ist das Verändern der Inhalte eines dynamischen Arrays innerhalb der Procedure ohne var-Übergabe genauso möglich wie mit var-Übergabe. Um das interne kopieren zu vermeiden, macht es Sinn den Parameter mittels var zu übergeben (was ja eigentlich generell die Übergabe eines Zeigers bewirkt).

Damit ergibt sich aber automatisch, dass Delphi intern die Parameterübergabe für unterschiedliche Typen auch unterschiedlich händelt. Oder wird bei der Übergabe einer Objectinstanz auch intern kopiert? :gruebel:

Gruß oki


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:14 Uhr.
Seite 1 von 2  1 2   

Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf