Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

21

26.02.2014, 15:39

Zitat

Dumm ist leider nur, dass du erst beim kompilieren siehst.

Fehler fallen meist immer erst beim Kompilieren auf.
Bei VS wird Const Correctness und Member auch schon im Hintergrund durch die IDE überprüft.
Das Argument verstehe ich nicht.

Für saubere sichere Schnittstellen und gutes Design möchte ich für meinen Teil Const Correctness nicht mehr missen. So kann man Dinge problemlos als Referenz/Pointer herumreichen ohne Angst vor Seiteneffekten haben zu müssen und das nochmal extra irgendwo dokumentieren zu müssen. Ein bisschen Arbeit ist es, ja. Aber nicht zu viel.
"const" vergesse ich auch manchmal, bin dann allerdings glücklich wenn es direkt zu einem Fehler führt. Ab und zu vergesse ich es ohne dass es auffällt und sorgt erst später für kleine Problemchen, die sich aber zum Glück auch schnell wieder beheben lassen.
"IList<T>" ist auch wieder schreibbar und dein Punkt war ja, dass man mit "IEnumerable<T>" Schreibzugriff verhindern können soll.

Zitat von »TrommlBomml«

Naja, dass ich bin bis heute nicht überzeugt dass das die Performance-Killer sein sollen. Das hält sich doch im Nanosekundenbereich.

Es ist Tatsache, dass sie auf der CPU für Sprungvorhersage, Cache usw. das sehr sehr schlecht sind.
Nanosekunden hin oder her, sie stecken schließlich dann auch in den inneren Schleifen und entfalten ihre Wirkung an der Stelle dadurch gut.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

22

26.02.2014, 18:05

Ich möchte an dieser Stelle nur darauf hinweisen dass diese Diskussion ein wenig abzuschweifen droht. Etwas weniger Prinzipienkampf und mehr beim Thema bleiben bitte:) Sonst artet das hinterher in Seitenlangen Abspaltungen aus wie es so oft der Fall ist.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

23

26.02.2014, 21:54

Ganz ehrlich? IEnumerable ist schlecht, weil es virtual calls macht und weil es nicht zu reversen geht?
:whistling: premature optimisation :whistling:
Macht Euch Gedanken über Eure Algorithmen und logische Korrektheit und nicht darüber, ob eine Iteration nun ein paar Zyklen mehr oder weniger braucht. Diese Stellen waren zudem bisher so gut wie nie die Performance-Löcher in irgendeiner meiner praktischen Anwendungen. Die CPU-Killer stecken meist ganz woanders als in der Verwendung (oder nicht) eines IEnumerable-Interfaces.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

TrommlBomml

Community-Fossil

  • »TrommlBomml« ist der Autor dieses Themas

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

24

27.02.2014, 09:24

Wie gesagt, geht mit Reverse()-Erweiterungsmethoden ausserdem ;). Danke, dass mich aber einer mal versteht :)

Aber wenn du schonmal deinen Senf dazu gibst BlueCobold, wie ist deine Meinung zum ursprünglichen Thema?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

25

27.02.2014, 13:29

Ich würde sagen am besten natürlich gar nicht. Was der Königsweg da in C++ ist, das weiß ich nicht und will mich daher am liebsten vor der Antwort drücken. Keiner der Wege scheint mir sonderlich elegant, da selbst mit Iteratoren für begin und end der Typ der internen Collection disclosed wird. Das umgeht man bei C# durch das IEnumerable, welches ja nur ausdrückt, dass es eine Menge einer unbestimmten Ordnung und Struktur ist (wo ich dots Meinung nicht teilen kann - denn es muss keine Collection intern existieren, ich kann auch per yield lauter einzelne Variablen als IEnumerable zurückgeben oder multiple verschiedene Collections mergen). Das gibt's ja aber eben nicht.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlueCobold« (27.02.2014, 13:46)


Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

26

27.02.2014, 15:31

In C++ kann man die Iteratoren auch so herumreichen, dass der Typ dahinter versteckt ist.
Das "yield return" von C# geht in C++ auch, in dem man einfach einen eigene Iteratorklasse erstellt, so wie es in C# vor 2.0 auch war. (bzw. wie es jetzt im Hintergrund versteckt immer noch ist.)

Mit der Performance hast du im Prinzip schon recht, jedoch sind einige Algorithmen dadurch unmittelbar getroffen.
Zb. all die Dinge die bei C++ im "algorithm"-Header stecken wie beispielsweise "sort", sollen darunter leiden. "Reverse" ist auch ein gutes Beispiel. Wenn nur "IEnumerable<T>" zur Verfügung steht, müsste es ein sehr schlechtes Laufzeitverhalten haben. Getestet habe ich das allerdings noch nicht.
Und wenn man mit auch nur mittelgroßen Datenmengen hantiert, ist das schon von Bedeutung, wenn die Laufzeit x mal langsamer ist.

Ich habe nicht gesagt, man soll es nicht verwenden, nur man kann es aus den ganzen Gründen manchmal nicht verwenden und C++ bietet auf statische Weise fast das Gleiche und noch mehr. Meine Ursprungsaussage sollte eigentlich auch hauptsächlich sein, dass die "readonly"-Funktionalität in C++ definitiv umfassender funktioniert.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

27

27.02.2014, 16:03

Ein yield return ist kein Iterator. Auch nicht versteckt. Das funktioniert komplett anders. :rolleyes:
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

28

27.02.2014, 17:11

Doch, der Compiler erzeugt im Hintergrund eine von "IEnumerable<T>"(und einigen anderen Interfaces) abgeleitete private Klasse(Also im Prinzip einen "C#-Iterator").Das kann man auch selbst ganz schnell herausfinden, in dem man zb. mit dem .Net Reflector eine entsprechende Binary untersucht. Eine "yield return"-Funktion kann auch komplett manuell erstellen. Bei C# bis 1.1 und C++ notwendigerweise. "yield return" ist natürlich trotzdem praktisch.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

29

27.02.2014, 17:19

Der Unterschied ist nur der ganz kleine, dass der Code in C# komplett umgeschrieben wird. Das lässt sich also nicht durch einen generischen Iterator lösen, sondern erfordert Compiler-Support, außer man will für jede Methode einen neuen Iterator schreiben - was natürlich unnützer Overkill ist.
Ändert aber dennoch auch nichts daran, dass außer mit einem eigenen Iterator sich nach außen in C++ nicht verstecken lässt welcher Collection-Typ intern verwendet wird. Irgendwie nicht sehr elegant, denn da muss man eben pro Klasse oder gar pro Methode einen eigenen Iterator implementieren, wenn man es nicht disclosen will. Das kann irgendwie nicht im Sinne des Erfinders sein.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

30

27.02.2014, 17:39

In meinen Fall habe ich konkret zwei Objekte. Eines verwaltet Objekte in einer Baumstruktur und dient zur Aktualisierung der Daten, in diesem Fall ein SceneGraph. Der SceneGraph besitzt diese ganzen Objekte und aktualisiert diese. Es ist aber nicht seine Aufgabe, die Objekte auch zu rendern. Dafür gibt es das SceneRenderer-Interface, der einen SceneGraph kennt und seine Objekte sequentiell zum Rendern erhalten muss, um ggf. optimierungen in der Zeichenreihenfolge etc. vorzunehmen. Es ist ja wohl nicht gut, wenn der SceneGraph auch rendert. Und das sortieren ist abhängig vom Renderverfahren (Deferred, Forward, verschiedene Qualitätsabstufungen, mit Ohne Postprocessing, etc.) und somit ist diese Aufgabe extra in einem Interface angebildet. Daher muss SceneRenderer irgendwie die Objekte aus dem SceneGraphen erhalten und verarbeiten.

Visitor Pattern: Schick den SceneRenderer durch den SceneGraph und jeder Node, der eine visuelle Ausgabe haben soll, trägt entsprechende Visual Objekte ein. Und schon ist die ganze Iterationslogik im SceneGraph gekapselt, wo sie auch hingehört. Rendering und Scenegraph sind wunderschön entkoppelt, den Renderer braucht es nicht zu interessieren, wie genau der SceneGraph für diesen konkreten Fall traversiert werden muss und den SceneGraph braucht es nicht zu interessieren, in was für eine Struktur der Renderer seine Visuals speichert; nirgendo muss etwas unnötig kopiert, irgendwelche Iteratoren herumgereicht (IEnumerable ist, wie gesagt, nichts anderes als eine ganz spezielle Art von Iterator) oder gar interne Container exposed werden. Hat den weiteren Vorteil, dass ein Node auch gern mehrere oder gar keine Visuals haben kann...

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »dot« (27.02.2014, 17:46)


Werbeanzeige