Autor Beitrag
sky21
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 141

W7
D2010, XE2
BeitragVerfasst: Di 28.07.09 15:30 
Ich habe ein Blackout bezüglich "Speicherfreigabe".

Es geht um Folgendes: Ich instanziere ein Objekt und übergebe dies einer Funktion CheckIt(). Was macht aber CheckIt() genau? Meiner Meinung nach eine lokale Kopie. D.h. ich habe dann 2x die Daten, richtig? Was bewirkt dann ein Free() auf dem übergebenen Objekt? was konkret wird jetzt freigegeben? Ich schnall's im Moment echt nicht.

PS: ...hab mir gerade überlegt, ob es einfacher wäre, einfach Pointers zu übergeben ...


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
// Die Klassen: Eine Basisklasse, zwei Subklassen. Fertig
type
  PClassBase = ^TClassBase;
  TClassBase = class(Tobject)
  public
    procedure foo(aVal : Integer);
    constructor Create;
end;

type
  PClassSubA = ^TClassSubA;
  TClassSubA = class(TClassBase)
  public
    constructor Create;
end;
type
  PClassSubB = ^TClassSubB;
  TClassSubB = class(TClassBase)
  public
    constructor Create;
end;


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure TForm2.ButtonClick(Sender: TObject);
begin
  Checkit( TClassSubB.Create() );
end;

procedure TForm2.Checkit(obj : TClassBase);
begin

  if (obj is TClassSubA) then
  begin
    obj.foo(1);
  end
  else if (obj is TClassSubB) then
  begin
    obj.foo(2);
  end
  else
  begin
    obj.foo(-1);
  end;

  obj.free;
end;
Tastaro
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 414
Erhaltene Danke: 23



BeitragVerfasst: Di 28.07.09 15:52 
In deinem Fall hast due das Objekt nur genau 1x und es wird durch das .free in checkit freigegeben.

Ist möglich, aber nicht schön, da imemr da freigegeben werden sollte wo auch erzeugt wird.
Also wäre das viel hübscher:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
procedure TForm2.ButtonClick(Sender: TObject);
var
   CheckObject: TClassSubB; 
begin
   CheckObject := TClassSubB.Create();
   Checkit( CheckObject );
   CheckObject.free;
end;

procedure TForm2.Checkit(obj : TClassBase);
begin

  if (obj is TClassSubA) then
  begin
    obj.foo(1);
  end
  else if (obj is TClassSubB) then
  begin
    obj.foo(2);
  end
  else
  begin
    obj.foo(-1);
  end;
end;
[/quote]

Achja: Und Zeiger braucht man gar nicht, wenn man Objekte hat.

Beste Grüße
sky21 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 141

W7
D2010, XE2
BeitragVerfasst: Di 28.07.09 16:01 
Danke für die schnelle Antwort. Ich bin da vollkommen gleicher Meinung, dass Erzeugung und Zerstörung im selben Codeblock erfolgend sollte. Aber das geht ja nur, wenn die Abarbeitung (z.b. dann bei CheckIt()) synchron funktioniert.

Trotzdem eine Verständnisfrage:
Was genau wird eigentlich der Funktion übergeben? Lokele Kopie? Adresse? Ich bin da noch verwirrt, denn üblicherweise arbeite ich in solchen Fällen dann mit dem "var" Zusatz.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 28.07.09 16:04 
Moin!

Bitte ändere den Titel des Topics, da er wenig über das eigentlich Thema verrät. Hier der entsprechende Absatz aus den Richtlinien:
1.2 Beiträge:
Bitte formuliere den Betreff Deiner Beiträge so, dass andere Mitglieder anhand dieser bereits das eigentliche Thema festmachen können. Beiträge wie etwa "Eine Anfängerfrage" oder "Weiß jemand, wie das geht?" lassen den Leser im Unklaren darüber, was das Thema der Diskussion ist.[...]
Einfach oben bei Deinem ersten Beitrag auf user defined image oder user defined image klicken und den Titel ändern. Danke Dir!

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Tastaro
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 414
Erhaltene Danke: 23



BeitragVerfasst: Di 28.07.09 16:07 
user profile iconsky21 hat folgendes geschrieben Zum zitierten Posting springen:
Danke für die schnelle Antwort. Ich bin da vollkommen gleicher Meinung, dass Erzeugung und Zerstörung im selben Codeblock erfolgend sollte. Aber das geht ja nur, wenn die Abarbeitung (z.b. dann bei CheckIt()) synchron funktioniert.

Trotzdem eine Verständnisfrage:
Was genau wird eigentlich der Funktion übergeben? Lokele Kopie? Adresse? Ich bin da noch verwirrt, denn üblicherweise arbeite ich in solchen Fällen dann mit dem "var" Zusatz.


Übergeben wird eine sog. Referenz. Also keine Kopie des Objekts, sondern nur ein Verweis darauf.

Siehe auch:
de.wikipedia.org/wik...eferenz_(Informatik)

Beste Grüße
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Di 28.07.09 20:16 
user profile iconsky21 hat folgendes geschrieben Zum zitierten Posting springen:
Was genau wird eigentlich der Funktion übergeben? Lokele Kopie? Adresse?

Adresse.

user profile iconsky21 hat folgendes geschrieben Zum zitierten Posting springen:
Ich bin da noch verwirrt, denn üblicherweise arbeite ich in solchen Fällen dann mit dem "var" Zusatz.

Da du dazu auch noch mit Pointers arbeitest, solltest du dir eines klarmachen: TObject = Pointer. Objektinstanzen sind immer nur Verweise auf die Objekte selbst. Da diese im RAM liegen und das auch tun müssen, können sie nicht einfach als Parameter übergeben werden (Parameter sind im Stack).

Wenn du dennoch sogenannte Wertetypen bzw. Werteparameter brauchst, dann nimm Records.
Pass aber auf, dass du keine dynamischen Arrays dadrin verwendest, denn die sind wieder Referenztypen - das hat mir mehrere Stunden nervige Fehlersuche eingebracht :autsch:
Tastaro
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 414
Erhaltene Danke: 23



BeitragVerfasst: Di 28.07.09 23:36 
user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconsky21 hat folgendes geschrieben Zum zitierten Posting springen:
Was genau wird eigentlich der Funktion übergeben? Lokele Kopie? Adresse?

Adresse.

Nein, eine Referenz. Siehe de.wikipedia.org/wik...enz_%28Informatik%29

user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconsky21 hat folgendes geschrieben Zum zitierten Posting springen:
Ich bin da noch verwirrt, denn üblicherweise arbeite ich in solchen Fällen dann mit dem "var" Zusatz.

Da du dazu auch noch mit Pointers arbeitest, solltest du dir eines klarmachen: TObject = Pointer.

TObjekt ist eine Klasse und kein Objekt. Das hat erst mal gar nix mit Zeigern zu tun.
Legt man eine Instanz der Klasse an, erhält man eine Referenz für ein Objekt. Dass das irgendwo ein Zeiger wird braucht aber einen Entwickler der in Delphi schreibt erst mal gar nicht zu interessieren, denn für den sind Referenzen und Zeiger zwei ganz verschiedenen Dinge.

user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:

Objektinstanzen sind immer nur Verweise auf die Objekte selbst. Da diese im RAM liegen und das auch tun müssen, können sie nicht einfach als Parameter übergeben werden (Parameter sind im Stack).

Verweise (= Referenzen) ermöglichen zwar den Zugriff auf Instanzen von Objekte, aber dadurch sind die Verweise nicht identisch mit Instanzen. Diese Verweise lassen sich sehr wohl ganz einfach als Parameter übergeben. (siehe oben)

user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:

Wenn du dennoch sogenannte Wertetypen bzw. Werteparameter brauchst, dann nimm Records.
Pass aber auf, dass du keine dynamischen Arrays dadrin verwendest, denn die sind wieder Referenztypen - das hat mir mehrere Stunden nervige Fehlersuche eingebracht :autsch:


Ich bin der festen Überzeugung, dass man keine Records braucht, wenn man Klassen hat. Aber da gehen die Meinungen hin und wieder auseinander.

Beste Grüße
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Di 28.07.09 23:46 
user profile iconTastaro hat folgendes geschrieben Zum zitierten Posting springen:

Ich bin der festen Überzeugung, dass man keine Records braucht, wenn man Klassen hat. Aber da gehen die Meinungen hin und wieder auseinander.


Naja, es gibt auch Gelegenheiten, wo eine eigene Klasse mit Kanonen auf Spatzen geschossen wäre.
Oder würdest du TPoint als Klasse implementieren?
mfg Boldar
Tastaro
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 414
Erhaltene Danke: 23



BeitragVerfasst: Mi 29.07.09 07:28 
user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconTastaro hat folgendes geschrieben Zum zitierten Posting springen:

Ich bin der festen Überzeugung, dass man keine Records braucht, wenn man Klassen hat. Aber da gehen die Meinungen hin und wieder auseinander.


Naja, es gibt auch Gelegenheiten, wo eine eigene Klasse mit Kanonen auf Spatzen geschossen wäre.
Oder würdest du TPoint als Klasse implementieren?
mfg Boldar


Warum nicht? Aber wie schon geschrieben: Da gehen die Meinungen auseinander. :)
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 29.07.09 11:26 
Moin!

user profile iconTastaro hat folgendes geschrieben Zum zitierten Posting springen:
Ich bin der festen Überzeugung, dass man keine Records braucht, wenn man Klassen hat.
Theoretisch: ja, praktisch: nein. :| Bedien´ mal die Windows-API ohne records... 8)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Mi 29.07.09 11:31 
user profile iconTastaro hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconsky21 hat folgendes geschrieben Zum zitierten Posting springen:
Was genau wird eigentlich der Funktion übergeben? Lokele Kopie? Adresse?

Adresse.

Nein, eine Referenz. Siehe de.wikipedia.org/wik...enz_%28Informatik%29

Naja, laut Wikipedia ist eine Referenz ein Zeiger, mit dem es sich leichter arbeiten lässt und der weniger fehleranfällig ist. Technisch gesehen ist das eigentlich kein großer Unterschied.

user profile iconTastaro hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconsky21 hat folgendes geschrieben Zum zitierten Posting springen:
Ich bin da noch verwirrt, denn üblicherweise arbeite ich in solchen Fällen dann mit dem "var" Zusatz.

Da du dazu auch noch mit Pointers arbeitest, solltest du dir eines klarmachen: TObject = Pointer.

TObjekt ist eine Klasse und kein Objekt.

TObject ist ein Datentyp. Deklariert man eine Variable des Typs TObject, beschreibt diese Variable eine Referenz, also eine Art Zeiger. Man hätte theoretisch auch eine Variable des Typs Pointer deklarieren können und ihr zum Beispiel TObject.Create zuweisen können. Alles möglich.

user profile iconTastaro hat folgendes geschrieben Zum zitierten Posting springen:
Das hat erst mal gar nix mit Zeigern zu tun.

Genau hier ist der Punkt: Wenn man Referenz mit Zeiger gleichsetzt, stimmt das von mir geschriebene. Wenn nicht, nicht ;)

user profile iconTastaro hat folgendes geschrieben Zum zitierten Posting springen:
Legt man eine Instanz der Klasse an, erhält man eine Referenz für ein Objekt. Dass das irgendwo ein Zeiger wird braucht aber einen Entwickler der in Delphi schreibt erst mal gar nicht zu interessieren, denn für den sind Referenzen und Zeiger zwei ganz verschiedenen Dinge.

Stimmt natürlich, aber es kann ihn interessieren und mich tut es das ;)

user profile iconTastaro hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:

Objektinstanzen sind immer nur Verweise auf die Objekte selbst. Da diese im RAM liegen und das auch tun müssen, können sie nicht einfach als Parameter übergeben werden (Parameter sind im Stack).

Verweise (= Referenzen) ermöglichen zwar den Zugriff auf Instanzen von Objekte, aber dadurch sind die Verweise nicht identisch mit Instanzen. Diese Verweise lassen sich sehr wohl ganz einfach als Parameter übergeben. (siehe oben)

Ok, ich meinte nicht Objektinstanzen, sondern Variablen des Typs TObject. Hab' mir irgendwann mal in den Kopf gesetzt, dass Variablen Instanzen sind. Das ist irreführend.

user profile iconTastaro hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:

Wenn du dennoch sogenannte Wertetypen bzw. Werteparameter brauchst, dann nimm Records.
Pass aber auf, dass du keine dynamischen Arrays dadrin verwendest, denn die sind wieder Referenztypen - das hat mir mehrere Stunden nervige Fehlersuche eingebracht :autsch:


Ich bin der festen Überzeugung, dass man keine Records braucht, wenn man Klassen hat. Aber da gehen die Meinungen hin und wieder auseinander.

Stimmt schon, wer Records benutzt, ist faul. Zu faul, die Instanzen zu initialisieren, zu faul, um eine Zuweisung à la Assign durchzuführen etc. Mit OOP haben Records wenig zu tun. Aber ich schweife vom Thema ab.

Grüße,
Yogu
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mi 29.07.09 11:31 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconTastaro hat folgendes geschrieben Zum zitierten Posting springen:
Ich bin der festen Überzeugung, dass man keine Records braucht, wenn man Klassen hat.
Theoretisch: ja, praktisch: nein. :| Bedien´ mal die Windows-API ohne records... 8)

Soll das eine Herausforderung werden :mrgreen:

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 29.07.09 11:33 
Moin!

user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconTastaro hat folgendes geschrieben Zum zitierten Posting springen:
Ich bin der festen Überzeugung, dass man keine Records braucht, wenn man Klassen hat.
Theoretisch: ja, praktisch: nein. :| Bedien´ mal die Windows-API ohne records... 8)

Soll das eine Herausforderung werden :mrgreen:
Wenn du dich angesprochen fühlst: nur zu! :D

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Aya
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: Mi 29.07.09 12:15 
@Records oder Klassen:

In sprachen wie C++ trifft es zu das records/structs überflüssig sind (wobei es da afaik sowieso intern vom compiler identisch behandelt wird.. nur das beim record per standard alles public, bei der klasse alles private ist)..

Bei Delpti allerdings macht es einen riesen Unterschied ob man Records oder Klassen benutzt!

Klassen werden jedesmal via create() erzeugt und landen somit im RAM, jeder zugriff darauf dauert länger als auf einen Record der im Stack liegt. Das mag bei 0815-Anwendungen egal sein.. aber für aufwändige Algorithmen oder Spiele etc ist das ein riesen Zeitgewinn/verlust.

Aya

_________________
Aya
I aim for my endless dreams and I know they will come true!
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mi 29.07.09 12:20 
user profile iconAya hat folgendes geschrieben Zum zitierten Posting springen:
@Records oder Klassen:

In sprachen wie C++ trifft es zu das records/structs überflüssig sind (wobei es da afaik sowieso intern vom compiler identisch behandelt wird.. nur das beim record per standard alles public, bei der klasse alles private ist)..

Hat noch paar andere Implikationen; u.a. wegen Vererbung ...

user profile iconAya hat folgendes geschrieben Zum zitierten Posting springen:
Bei Delpti allerdings macht es einen riesen Unterschied ob man Records oder Klassen benutzt!

Jep ...

user profile iconAya hat folgendes geschrieben Zum zitierten Posting springen:
Klassen werden jedesmal via create() erzeugt und landen somit im RAM, jeder zugriff darauf dauert länger als auf einen Record der im Stack liegt.

Und wo liegt bitte schön der Stack? Sag jetzt bloß nicht im CPU-Cache :P Außerdem: Globale Variablen liegen nicht im Stack.

user profile iconAya hat folgendes geschrieben Zum zitierten Posting springen:
Das mag bei 0815-Anwendungen egal sein.. aber für aufwändige Algorithmen oder Spiele etc ist das ein riesen Zeitgewinn/verlust.

Aya
Ich verzichte grad mal, darauf näher einzugehen ... Nicht alles was von Apple kommt ist ein Mac.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.