Autor |
Beitrag |
pi31415
Hält's aus hier
Beiträge: 4
|
Verfasst: Do 01.05.08 22:29
Hallo zusammen,
ich hoffe ich mache mich nicht gleich unbeliebt und poste in die falsche Abteilung oder gehe euch mit meinen Anfängerfragen auf die Nerven.
Nachdem ich mittlerweile HTML und PHP einigermassen kann habe ich Delphi asuerkoren um irgendwann mal Windowsanwendungen mit Webapplikationen zu verknüpfen.
Nun habe ich einfach mit dem Wikipediascript losgelegt und hänge nun bei dem Pointerbeispiel fest, was dann so aussieht:
Moderiert von Christian S.: Siehe Anhang
Ist das wiki Beispiel für Pascal gedacht? Hab ich mit dem Kopieren und Einfügen irgendeinen Fehler gemacht?
Da mir Zeiger ziemlich neu sind würde ich schon gerne sehen was dieses Beispiel bewirken soll.
Gruß aus Berlin,
Jan
Moderiert von Christian S.: Bild als Anhang eingefügt
Einloggen, um Attachments anzusehen!
Zuletzt bearbeitet von pi31415 am Fr 23.05.08 22:23, insgesamt 1-mal bearbeitet
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: Do 01.05.08 23:03
Hi und  im Forum.
Einen Fehler kann ich nicht erkennen.
Ich machs mal ausführlich:
Das Dach vor dem Typ - in diesem Fall ein Integer - signalisiert dem Compiler, dass es sich hierbei um einen Pointer handelt.
Hier wird zunächst der Variablen i der Wert 1 zugewießen.
Anschließend erhält der Pointer p1 die Speicheradresse der Variablen i.
Delphi-Quelltext
Das Dach (^) hinter dem Pointer bzw. der Variable kennzeichnet eine Wertübergabe. Würde das Postfix fehlen, so würde sich die Speicheradresse in p1 ändern!
Delphi-Quelltext 1: 2:
| p1^ := p1^+1; j := p1^; |
Letztendlich wird i um eins inkrementiert, anschließend bekommt j diesen Wert zugewießen.
Aber wird dies nicht auch alles bereits bei Wiki erklärt?
Cheers,
Marc
|
|
pi31415 
Hält's aus hier
Beiträge: 4
|
Verfasst: Fr 02.05.08 00:57
Danke für die ausführliche Antwort.
Die Pointer muss ich wohl erstmal ohne praktisches Besipiel dahingestellt lassen. Ich verstehe sehrwohl was das ^ oder das @ bedeuten, aber das ändert nichts daran, daß der Beispielquelltext aus dem Wikiscript beim Starten mit F9 in der Turbo Delphi Umgebung nicht funktioniert.
Auf dem Screenshot aus dem ersten Post sollte auch zu erkennen sein das die Zeile 10 rot unterlegt ist und bei den Meldungen ein Haufen Fehler erscheinen.
Für mein Verständniß wär es toll gewesen wenn dieses Beispielprogramm wenigsten funktioniert hätte oder sogar etwas wie eine Speicheradresse ausgespuckt hätte.
Wie kann ich mir denn eine Speicheradresse nun beispielsweise ausgeben? Mit den 2 Befehlen die ich mittlerweile kann war es irgendwie klar das writetln() nicht damit umgehen kann.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| var i: Integer; p1 : ^Integer; begin i := 1; p1 := @i; writeln(p1); readln; end. |
Wie gesagt sind Zeiger ohne praktisches Beispiel irgendwie Abstrakt, muß mich wohl ertsmal weiter durchwurschteln.
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Fr 02.05.08 09:16
Also ich kann dir da nur zustimmen. Pointer ohne wirklich praktischen Nutzen sind eher nicht so einfach zu verstehen.
Zum dem Code. Pointerdeklarationen innerhalb des Var Teils sind kein guter Stil. Sollte aber eigentlich trotzdem funktionieren. Ich würde dir aber trotzdem empfehlen einen direkten Pointertypen zu deklarieren und dann diesen zu benutzen.
Delphi-Quelltext 1: 2: 3: 4:
| type PInteger = ^Integer; var P1: PInteger |
Diese Typen sollten aber schon von Hause aus definiert sein. Weswegen du keinen eigenen Typen definieren müsstest.
Zur Ausgabe / Zugriff auf die Adresse brauchst du lediglich die Pointervariable wie eine Integervariable behandeln. Also IntToHex(Cardinal(Pointer), 8);. Dann wird ganz normal der Wert der Variable benutzt. Also die Adresse. Zum Zugriff die Daten auf die der Pointer zeigt musst du sie wieder dereferenzieren.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Fr 02.05.08 10:22
Dein Programm darf entweder nicht Pointer heissen oder du musst bei der Variablendeklaration System.Pointer schreiben.
Wenn du normale Windowsanwendungen schreibst und Wert auf ein sauberes Codedesign legst wirst du nie einen Pointer brauchen. Ich würde an einer anderen Stelle beginnen.
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Di 06.05.08 14:01
Auch wenn es ziemlich spät und sehr offtopic ist muss ich dazu noch was sagen, weil ich persönlich das so nicht stehen lassen kann und will.
delfiphan hat folgendes geschrieben: | Wenn du normale Windowsanwendungen schreibst und Wert auf ein sauberes Codedesign legst wirst du nie einen Pointer brauchen. |
Klar kann man sein Programm immer so schreiben, dass man auf Pointer verzichten kann. Es wird ja niemand dazu genötigt Pointer zu benutzen. Aber an einigen Stellen sollte man sich stark überleben ob es nicht evtl. sinnvoll ist sich mit Pointern auseinander zu setzen. Denn je nach Situation (nicht immer) bieten diese durchaus mehr Vorteile als eine pointerlose Struktur. Was sich letzten Endes im Programmierkomfort sowie in der Geschwindigkeit positiv wiederspiegeln kann.
Und nur weil man Pointer benutzt heißt es noch lange nicht, dass man ein unsauberes Codedesign hat. Andersrum heißt es auch nicht, dass man ein sauberes Design hat nur weil man keine Pointer hat. Um seinen Code zu vermurksen hat man sehr sehr viele Chancen.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Di 06.05.08 21:25
Lossy eX hat folgendes geschrieben: | Und nur weil man Pointer benutzt heißt es noch lange nicht, dass man ein unsauberes Codedesign hat. Andersrum heißt es auch nicht, dass man ein sauberes Design hat nur weil man keine Pointer hat. Um seinen Code zu vermurksen hat man sehr sehr viele Chancen. |
Allgemein ausgeschlossen habe ich die Pointer nicht. Pointer sind für mich aber lowlevel und gehören nicht in highlevel Code. Ich sage nicht, dass man in jedem Fall auf Pointer verzichten muss und es ist bestimmt bis zu einem gewissen Grad Geschmackssache. Das hängt von der Art von Code ab, die man schreibt, etc..
Wenn man jedoch normale Fensteranwendungen ("highlevel-Code") schreibt, weiss ich nicht, was die Pointer Positives bringen sollten. Und ob man in der Fachliteratur über Codedesign gross Empfehlungen findest, Pointer zu verwenden, bin ich mir relativ unsicher 
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Mi 07.05.08 09:34
delfiphan hat folgendes geschrieben: | Allgemein ausgeschlossen habe ich die Pointer nicht. |
Klang für meinen Geschack fast so.
Bei dem Rest hast du durchaus irgendwo recht. Dort ist eine gehörige Portion geschmacksache dabei und es hängt wirklich sehr stark davon ab was man überhaupt machen will. Für mich ist Code "normal" der irgendwas mit Bitmaps oder mit verschiedene Datenstrukturen (Bäume, Hashs oder Schlimmeres) zu tun hat und da kommt man einfach nicht an Pointern vorbei. Selbst bei Windowsprogrammen kommt es es häufig genug vor. Ich persönlich versuche so lange wie möglich auf die Pointerschubserei zu verzichten allerdings wenn ich denke es lohnt sich, dann setze ich sie ein. Und da denke ich kann man Pointerbenutzung einfach nicht verpauschalisieren und es gibt an einigen Stellen keine genaue Trennung zwischen Low und High Level. (Sehe ich zu mindest bei Delphi/Pascal so)
Ich sehe das Ganze aber auch noch von einer anderen Seite. Wenn jemand gerade mit Pointern anfängt und er dann gesagt bekommt, dass Pointer "böse / schlechter Stil" (kein Zitat) sind kann es gut sein, dass derjenige Pointer dann sein lässt. Aber für meinen Geschmack sind Pointer dafür viel zu sehr ein integraler Bestandteil der Programmierung. Selbst, wenn man sie nicht bewusst einsetzt sondern die Sprache das für einen tut. Zu wissen was in seinem eigenen Code passiert kann nicht schaden.
Nichts desto trotz sollte jedem, der Pointer benutzt, klar sein, dass sie reichlich gefährliches Potential haben und man sich damit sehr sehr schnell Dinge kaputt machen kann! Aber ich würde keine pauschale Aussage treffen, wann etwas Sinn macht und wann nicht. Das liegt immer im Ermessen des Einzelnen.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
hazard999
      
Beiträge: 162
Win XP SP2
VS 2010 Ultimate, CC.Net, Unity, Pex, Moles, DevExpress eXpress App
|
Verfasst: Mi 07.05.08 10:06
Hallo,
also für Win32-Anwendungen lasse ich "Geschwindigkeitsvorteil" nicht gelten.
Objektreferenzen sind zwar auch Pointer, allerdings streng typisiert.
Ich würde niemals strenge Typisierung für 20 CPU-Zyklen eintauschen.
Ausserdem liegt der Löwenanteil der Applikationen in einem Bereich bei dem solche Konstrukte nicht notwendig sind.
Den grössten Teil der Zeit verbraucht man normalerweise beim Zugriff auf langsame Resourcen (Datenbank, Filesystem, Network I/0).
Man kann mit Pointern defacto nur bei sehr speziellen Anwendungen Zeit sparen.
Hierbei muss alles im RAM liegen und die Datenmenge so groß sein das hier wirklich ein unterschied besteht.
Für die Standard-Liste oder Baum: TList und TObject.
Ich persönlich habe bis jetzt nur einen Fall gehabt:
Einlesen von sehr großen ESRI-Shape Dateien plus zeichnen am Canvas. Da hats Sinn gemacht.
r u
René
_________________ MOV EAX, Result;MOV BYTE PTR [EAX], $B9;MOV ECX, M.Data;MOV DWORD PTR [EAX+$1], ECX;MOV BYTE PTR [EAX+$5], $5A;MOV BYTE PTR [EAX+$6], $51;MOV BYTE PTR [EAX+$7], $52;MOV BYTE PTR [EAX+$8], $B9;MOV ECX, M.Code;MOV DWORD PTR [EAX+$9], ECX
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Mi 07.05.08 11:47
Ich habe ja nicht gesagt, dass es durch Pointernutzung automatisch schneller wird! Ich habe lediglich gesagt, dass es sich "in der Geschwindigkeit positiv wiederspiegeln kann." Ich persönlich habe es schon einige Male erlebt, dass die Mittel von Delphi (TList) nicht mehr gereicht haben. Aber ja. Um Geschwindigkeit zu bekommen muss man den Vorteil von Pointern auch wirklich nutzen. Und dabei müssen sich logischerweise die Daten im Speicher befinden und auch mehr als nur 10 bis 100 Instanzen existieren. Aber selbst dann kommt es auf ein entsprechenden Aufbau des Codes an. Der größte Vorteil von Pointern kann durch eine blödsinnige Berechnung wieder zu nichte gemacht werden. Und man muss auch immer abwägen ob eine entsprechende Optimierung Sinn macht. Wenn der Code nur ein Mal beim Drücken eines Buttons ausgeführt wird, dann macht es wohl keinen Sinn dort 10 ms einzusparen. Aber so etwas hängt immer vom Einzelfall ab! Und ich habe das nie auf Win32 only beschränkt sondern immer aufs Programmieren im Allgemeinen bezogen.
Du hast insofern durchaus auch recht, dass man bei üblichen Windows Anwendungen eher weniger Pointer benötigt. Allerding auch da kommt es wieder auf den Einzellfall an! Wenn du den VirtualTree von Mike Lischke verwendest, dann wirst du um Pointer nicht umherum kommen. Genau so, bei reichlich Methoden der Windows API, Speicherzugriff eines TBitmaps oder falls man mal mit DLLs etwas machen will. Und man sollte immer bedenken. Jedes Programm ist anders. Nur weil ich etwas nicht mache heißt es noch lange nicht, dass es niemand anders machen wird! Wenn das zutreffen würde, dann würde das ein oder andere Fernsehdisaster schon lange nicht mehr gesendet werden.
Zu Instanzen von TObject. Ja das sind Pointer. Ich weiß das und du weißt das auch. Allerdings habe ich es schon so häufig erlebt, dass Pointer auf TObjekt Typen deklariert und komische Dinge damit veranstaltet wurden. Letzen Endes wurde dadurch nur die Anwendung fehlerhaft. Und das spiegelt ja nur das wieder was ich sage.
Ich sage ja nicht, dass ab sofort jeder mit Pointern arbeiten soll/muss. Ich sage nur, dass man zu mindest wissen sollte wie sie funktionieren. Und falls man mal in die Situation kommt sie wirklich sinnvoll einsetzen zu können, dann sollte man das auch durchaus tun können. Aber dazu muss man wissen wie sie funktionieren. Wenn man von Anfang an aber gesagt bekommt "Bitte. Tu das nicht!", dann weiß man nicht wo und wie man sie einsetzen kann und wo man es besser bleiben lässt. Darum geht es mir.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
hazard999
      
Beiträge: 162
Win XP SP2
VS 2010 Ultimate, CC.Net, Unity, Pex, Moles, DevExpress eXpress App
|
Verfasst: Mi 07.05.08 13:45
Ok. Hab ich schlecht formuliert. Wollte deinen Post auf keinen Fall angreifen.
Ich wollte nur ausdrücken das man die Vorteile die man ohne direkte Verwendung von Pointern im Code hat teilweise verliert.
Ich persönlich arbeite lieber mit Klassen (Bäumen und Listen von Objekten) und erhalte mir die Vorteile die mir der Delphi-Compiler bietet.
Ein klassischer Pointer lässt sich halt mal in etwas casten was er eigentlich nicht representiert, ohne das der Compiler meckert.
Es sind sehr viele Dinge zu beachten, die das direkte Programmieren mit Pointer (vorallem für Anfänger) sehr schwer machen:
Größe von Datentypen (unterschiedliche Betriebssysteme)
Range-Checking
Speicherfragmentierung
Freigabe von Speicher (gilt auch für Objekte)
Speicherlecks durch Neuallozierung (gilt auch für Objekte)
...
Ich habe meine Aussage auf Win32-Anwendungen beschränkt da es bei anderen Anwendungen durchaus sinn macht bzw. man gar nicht anderst kann.
_________________ MOV EAX, Result;MOV BYTE PTR [EAX], $B9;MOV ECX, M.Data;MOV DWORD PTR [EAX+$1], ECX;MOV BYTE PTR [EAX+$5], $5A;MOV BYTE PTR [EAX+$6], $51;MOV BYTE PTR [EAX+$7], $52;MOV BYTE PTR [EAX+$8], $B9;MOV ECX, M.Code;MOV DWORD PTR [EAX+$9], ECX
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mi 07.05.08 19:42
Objektreferenz=Pointer: Wenn ich von Pointer spreche, dann meine ich natürlich nicht Objektreferenzen. Objektreferenzen sind keine Pointer (genauso wie Menschen keine Tiere sind). Ob die einander ähneln, ist irrelevant. Das ist eine Definitionsache.
WinAPI, DLL: Das ist lowlevel. Viel weiter lowlevel geht's ja nicht...
"Tu das nicht!": Das hat hier niemand behauptet. Ich sagte man solle als Anfänger nicht damit beginnen.
VirtualTree von Mike Lischke: Hab ich mir schnell angeschaut. Stimmt, er verwendet viel Pointer. Ist aber unnötig und das Design fragwürdig. Schau z.B. mal sein TVirtualNode-record an. Dort hat er einen Platzhalter am Schluss à la "Data: record end" und alloziert dann irgendwie mit GetMem je nach dem mehr oder weniger Speicher um da noch spezifische Daten anzuhängen. Für so Sachen gibt es Klassen und Vererbung. Ich könnte mir vorstellen, dass er diesen Weg geht, weil er dann mehrere Nodes im Speicher "am Stück" haben kann um die Performance zu steigern. Delphi erlaubt solche Sachen aber auch (ganz bewusst ohne Hacken) mit Objekten. Die ganze Pointerakrobatik ist meines Erachtens unnötig und das TVirtualNode ein Hack. Viel besser sind da die Codes von devexpress/QuantumGrid. Ich weiss nicht wieviele zigtausend Zeilen Code dort drinstecken, aber von Pointern sieht man nicht viel. Und dank der guten Architektur kann ich auch mal einen Node-Typ erweitern. Dass die Nodes dann über einen Datenbankcontroller irgendwo innerhalb der Architektur instanziert werden, ist dabei kein Hindernis. Mit Pointer kaum vorstellbar.
Design: Wenn du in Highlevelcode Pointer brauchst, ist das kaum im Sinne von gutem OOP-Design. Das Geschwindigkeitsargument ist nur sehr beschränkt ein Argument. Ich will nicht darüber streiten, ob es Einzelfälle gibt oder nicht. Die gibt es bestimmt. Aber dann ist's ein Kompromiss wegen VCL-Einschränkungen, schlechten Thirdparty-Komponenten oder Delphi-Spracheinschränkungen und ist nicht eigentlich im Sinne von gutem OOP-Design.
Oder nehmen wir die Eclipse IDE und Delphi 2007 IDE als weiteres Beispiel. Eclipse ist (für mich zu mindest) eindeutig stabiler und leistungsstärker. Das Beispiel zeigt, dass man sehr komplexe Programme schreiben kann, ohne jemals einen Pointer gebraucht zu haben (Java kennt keine Pointer) und ohne zwingend mit Geschwindigkeitseinbussen rechnen zu müssen. Es geht mir aber primär in der Diskussion um Highlevelcode in Fensterapplikationen und nicht um ganze Projekte; und schon gar nicht um Code in 3D-Engines oder in mathematischen Berechnungen.
|
|
hazard999
      
Beiträge: 162
Win XP SP2
VS 2010 Ultimate, CC.Net, Unity, Pex, Moles, DevExpress eXpress App
|
Verfasst: Do 08.05.08 08:22
WTF
Objectreferenzen sind Pointer...
try this...
Delphi-Quelltext 1:
| inttohex(longint(TObject.create), 8); |
_________________ MOV EAX, Result;MOV BYTE PTR [EAX], $B9;MOV ECX, M.Data;MOV DWORD PTR [EAX+$1], ECX;MOV BYTE PTR [EAX+$5], $5A;MOV BYTE PTR [EAX+$6], $51;MOV BYTE PTR [EAX+$7], $52;MOV BYTE PTR [EAX+$8], $B9;MOV ECX, M.Code;MOV DWORD PTR [EAX+$9], ECX
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Do 08.05.08 09:55
@hazard999: Hab ich evtl. auch etwas missverstanden. Falls ich da etwas forsch war (was zum Glück nie vorkommt) sag ich mal tschuldigung.
@delfiphan: In meinen Augen hat diese Diskussion ein ziemlich absurdes Level erreicht!! Was hat das denn mit Java zu tun? Dort wurde diese Frage bereits von der Sprache selbst beantwortet. Und es gibt nicht nur Fans von der krassen OOP Struktur. Und erhlich gesagt finde ich nahezu alle Java Programme im Vergleich zu nativen Anwendungen tierisch lahm und extrem Speicheritensiv. Aber dabei wird das Interpretationssystem auch seinen Teil zu bei tragen.
Meine Hauptaussage von oben ist immer noch folgende. Klar in High Level braucht man direkt keine Pointer. Da stimme ich dir auch voll zu. Aber bei wirklich komplexen Anwendungen dürfte es nahezu unmöglich sein wirklich ausschließlich nur High Level Code einzusetzen. Welche Gründe man dafür auch immer hat. Es gibt so viele Stellen an denen man wissen sollte ob es sich dabei um einen Pointer handelt oder nicht. Obwohl es auf den ersten Blick nicht immer ersichtlich ist. (long)Strings und TFileStream zum Beispiel. Deswegen kann man in meinen Augen nicht mal in normalen Fenster Anwendungen sagen, dass man immer High Level bleiben wird.
Und da gehts mir eher darum, dass man über Pointer aufklärt. Natürlich mit allen verbunden Gefahren und dem Hinweis, dass sich Anfänger eher nicht damit beschäftigen sollten! Aber man sollte es nicht von Hause aus ablehnen bzw als Schlecht abtun. In meinen Augen ist Unwissenheit viel riskanter als Pointer das sind.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Fr 09.05.08 14:08
@delfiphan: dass die Lösung mit dem Record beim VirtualTreeview ein Hack ist und es bessere Lösungen (mit Objekten, Klassen, Metaklassen, ..) gäbe ist zwar richtig, aber der VT ist auf höchste Performance getrimmt. Die Handhabung leidet zwar ein wenig darunter (vor allem auch deswegen weil der ganze VT extrem flexibel ist was natürlich auch die Komplexität erhöht), aber dafür ist es meines Wissens nach die mit abstand schnellste Implementierung eines Treeviews - auch schneller als die von DevExpress.
@rest: auf www.manuel-poeter.de findet man ein ausführliches Tutorial zum Thema Pointer. Darin enthalten ist auch ein Demo zur Implementierung einer doppelt verketteten Liste. Es gibt dabei 2 UI Versionen - eines mit der Delphi Listview und eines mit dem VirtualTreeview. Da ist der Geschwindigkeitsunterschied deutlich zu erkennen!
LG, Manuel
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Sa 10.05.08 14:08
@Motzi: Das stimmt nicht. Es existiert kein Geschwindigkeitsunterschied zwischen dynamisch erzeugten Records und Klasseninstanzen beim Zugriff auf Felder. Es wird nämlich der gleiche Maschinencode erzeugt. Der einzige Geschwindigkeitsunterschied entsteht beim Instanzieren durch "Batcherzeugnung", nur ist das bei Klassen eben genau so möglich, wie ich schon erläutert habe. Das einzige ist, dass die Klasseninstanz 4 Bytes mehr braucht. Für diesen nun wirklich vernachlässigbaren Preis erhält man aber automatisch Vererbung (und wohl auch noch eine besser wartbare Komponente). Ich könnte z.B. ganz einfach verschiedene Nodetypen in einem Tree haben (was relativ wichtig ist, wenn man komplexe Daten anzeigen will). Um das gleiche mit Records zu erreichen müsste ich zusätzliche Daten (z.B. über den Typ und Grösse der Zusatzdaten) mitspeichern und habe automatisch meinen 4-Byte-Vorsprung wieder verloren. Tja.
Aber das war nur ein Beispiel. Klar ist VirtualTree schnell. Ist auch mehr oder weniger WinAPI Code und hat sogar Teile in Assembler drin. Und ich streite mögliche Geschwindigkeitsvorteile bei Verwendung von Pointer nicht ab. Alles was ich ursprünglich sagen wollte ist, dass man als Anfänger vielleicht nicht als allererstes mit Pointern anfangen soll und man die auch nicht so schnell braucht.
Naja. Die Diskussion bringt nicht viel und ich will mich auch nicht ständig wiederholen. Es soll jeder so programmieren, wie er es für richtig hält. 
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Sa 10.05.08 16:11
Ich möchte die Diskussion nicht noch weiter aufheizen, aber ein paar Sachen möchte ich schon noch hinzufügen..
@delfiphan: dass die Verwendung von Klassen/Objekten in mancherlei Hinsicht besser wäre als Records ist unbestritten (hab ich ja auch weiter oben geschrieben), aber es hindert dich auch niemand daran NodeSize auf sizeof(TObject) zu setzen und als NodeData einfach eine Objektreferenz zu speichern. Das mach ich immer wenn ich unterschiedliche Nodetypen hab...
Und was den Geschwindigkeitsunterschied betrifft ist doch ein deutlicher Unterschied. Nicht was den Zugriff auf Felder betrifft, aber bei der Erzeugung. Für den Record reicht ein einfacher Aufruf von GetMem, für ein Objekt hingegen wird _ClassCreate aufgerufen welches erst einmal NewInstance aufgeruft, das seinerseits zuerst GetMem und dann noch InitInstance aufruft (welches den Speicher mit 0 initialisiert, den Self-Zeiger setzt und die Interface-Tabelle initialisiert). Anschließend wird mindestens noch ein Constructor (und eventuell auch noch ein paar vererbte) und AfterConstruction aufgerufen. Beim Erzeugen von Objekten passiert also doch einiges mehr und bei einigen 1000 Nodes macht sich dieser Unterschied doch deutlich bemerkbar. Außerdem verwaltet der VT seine Nodes in 16KB Blöcken wodurch wesentlich weniger GetMem Aufrufe notwendig sind. Ein ähnliches Verhalten wäre bei Objekten nur bedingt realisierbar indem man NewInstance überschreibt.
Aber du hast absolut recht, Pointer sind ein sehr komplexes Thema und als Anfänger sollte man sie meiden, da man damit sehr leicht mehr Schaden als Nutzen anrichtet.
LG, Manuel
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Sa 10.05.08 19:55
Nochmals: Ich habe eventuelle Geschwindigkeitsvorteile nicht bestritten. Sondern: Ich gewichte Stabilität und Erweiterbarkeit der Software, sowie schnelle und möglichst standardisierte Entwicklung höher als theoretische Spitzengeschwindigkeiten. Deswegen mag ich die Pointer in Highlevelcode nicht. Man muss alle Vorteile und Nachteile abwägen und diejenigen Nachteile bekämpfen, die am häufigsten Schwierigkeiten und schlussendlich Kundenreklamationen geben.
Motzi hat folgendes geschrieben: | bei einigen 1000 Nodes macht sich dieser Unterschied doch deutlich bemerkbar |
Ein paar 1000 sollten nicht ins Gewicht fallen. Man kann schon 10 Millionen Objekte in einer Sekunde kreieren. Ich würde mich aber fragen ob es wirklich nötig ist, zu Beginn schon 10 Millionen Objekte zu kreieren, denn wenn die Daten aus einer Datenbank kommen, dürfte die Instanzierung der Objekte nicht mehr der Flaschenhals sein.
Und: 10 Millionen Objekte dürften eine extreme Seltenheit sein. Klar, es ist immer möglich Spezialfälle zu finden, wo eine gewisse Implementierung besser ist als eine andere und ich habe auch nichts gegen Spezialoptimierungen für Spezialanwendungen, aber beim VirtualTree finde ich es zu mindest fragwürdig. Wenn die Klassen mal erzeugt sind, gibt's sowieso keinen Geschwindigkeitsunterschied mehr. Das Erzeugen geht halt etwas länger, ist aber mit entsprechenden Vorteilen verbunden, was die Anwendung von guten Designpatterns erst ermöglicht.
Motzi hat folgendes geschrieben: | Für den Record reicht ein einfacher Aufruf von GetMem, für ein Objekt hingegen wird _ClassCreate aufgerufen welches erst einmal NewInstance aufgeruft, das seinerseits zuerst GetMem und dann noch InitInstance aufruft (welches den Speicher mit 0 initialisiert, den Self-Zeiger setzt und die Interface-Tabelle initialisiert). Anschließend wird mindestens noch ein Constructor (und eventuell auch noch ein paar vererbte) und AfterConstruction aufgerufen. |
Das stimmt so nicht ganz. FillChar wird sinnvollerweise auch bei Records ausgeführt. Und wenn Afterconstruction & co. Grund zur Ablehung ist verbietet es dir ja niemand, die Klassen "von Hand" zu instanzieren und ein direktes Instanzieren zu verunmöglichen. Etwas, das ich definitiv nicht tun würde, aber meinem Geschmack gemäss immer noch hübscher ist als mit Pointern zu arbeiten. Denn durch die Spezialimplementierung über Record/Pointer zwingt die Komponente den Programmierer dazu, Pointer in Highlevel Code einzusetzen, was ich schlecht finde.
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: So 11.05.08 00:13
Also ich denke es kommt immer auf den Einzelfall drauf an. Da kann man meiner Meinung nach nicht sagen so oder so hat auszusehen zu müssen. Wenn ich Pointer benutze, dann sieht es meistens so aus, dass ich diese dann noch mal in einer extra Klasse kappsel. Einfach auch um das Risiko einer Falschbenutzung so gering wie möglich zu halten. An anderen Stellen benutze ich dann nur diese Klasse. Der "High Level" Code sieht dann nichts mehr von den Low Level Pointern obwohl ich sie selber eingebaut habe.
Die Handhabung beim VirtualTree ist sicher nicht die Beste. Das habe ich selber schon sehr genau mitbekommen dürfen. Das ist aber einfach so. Ich denke einen Teil seiner Geschwindigkeit stammt auch daher, dass er nicht so viel mit der API machen muss. Also das Design hätte man sicher auch anders machen können. Aber man hat bei OOP genau so viele Möglichkeiten das Design zu verhauen.
PS: Gewissermaßen ist doch jedes Programm ein Spezialfall. Welche 2 Programme sind schon identisch. Und man muss sich doch für jedes Programm immer wieder etwas neues einfallen lassen. Oder sich zu mindest ein entsprechendes Design ausdenken.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
|