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

dot

Supermoderator

  • »dot« ist der Autor dieses Themas

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

21

12.05.2016, 13:34

In deiner übergeordneten Struktur musst du dann aber automatisch manuell ein .close() implementieren, das die Ressourcen richtig freigibt. Desweiteren muss der Benutzer deiner übergeordneten Struktur auf einmal in allen Fällen korrekt .close() aufrufen. Ganz besonders toll wird es, wenn ein vorhandenes Objekt, das früher kein .close() brauchte auf einmal ein .close() bekommen muss, weil es einen neuen Member bekommen hat, der ein .close() braucht. Dann darf man sämtlichen Code durchforsten und schauen, dass ja es ja keinen möglichen Kontrollfluss gibt, der ohne .close() endet. Und wehe wenn am Ende noch eine weitere, übergeordnete Struktur existiert. Mit jeder Stufe darfst du dann exponentiell mehr Code anpassen und dabei hoffen, dass du ja nichts übersehen hast. Die ganze Idee von Kapselung und OOP war eigentlich, genau sowas (lokale Änderung an einer Klasse erzwingt Anpassung von sämtlichem Benutzercode) zu vermeiden...

In C++, bzw. generell in Sprachen, die RAII supporten (und RAII und GC schließen einander leider gegenseitig aus), macht der Compiler dagegen automatisch alles richtig, ohne dass du eine einzige Zeile Code dafür schreiben musst...

Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von »dot« (12.05.2016, 13:52)


DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

22

12.05.2016, 14:12

Hmm naja, alles richtig, lässt sich aber in den aller aller meisten Fällen vermeiden. Vielleicht haben wir einfach grundverschiedene Probleme :)
Übrigens was dein Java Beispiel angeht. Java schließt die Resource auch implizit bei einer exception: http://stackoverflow.com/questions/17650…urces-correctly Nicht schön ersichtlich finde ich...

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

23

12.05.2016, 14:13

wenn ich nur die Stunden zählen würde, die ich schon damit verbracht hab, irgendwelche obskuren Bugs zu suchen, die mit RAII niemals zustande gekommen wären...
Dito. In C++ wären entweder sofort durch korrekte Unique-Verwendung schlimme Design-Probleme aufgefallen, weil es sich damit nicht implementieren lässt oder es wären lauter tote Referenzen verwendet worden, bei denen das Programm schon während der Entwicklung viel öfter gecrasht wäre. Referenz-Sprachen mit Garbage-Collection verleiten Entwickler immer wieder zu Referenz-Zyklen und ähnlichem Mist, wo am Ende gar nichts mehr oder nur in übelartig großen Blöcken freigegeben wird. In Rust/Swift z.B. gibt es kein GC, sondern knallhartes Reference-Counting, was mit absoluter Präzision alles dann freigibt, wann es der Programmierer beabsichtigt, mit einem dazu sehr passendem und wichtigen weak-Reference-Konzept, was nicht "unpassend" obendraufgestülpt und für die meisten Entwickler total unbekannt ist - wie etwa in C# oder Java, wer bitte benutzt da schon weak references? Nur mit denen lassen sich Referenz-Zyklen aufbrechen und ein sauberes und deterministisches Speicherverhalten in einer Referenz-Sprache mit RefCounting sinnvoll umsetzen. In einer Referenz-Sprache mit GC geht aber auch nur eins davon - der Freigabezeitpunkt ist noch immer undefiniert.

Ich mochte C# früher sehr, ich mag auch die unglaublich große .Net Bibliothek total. Ich mag aber das Speicherverhalten von C++ deutlich mehr. Rust/Swift sind bei mir neuerdings eine gute Vereinigung beider Welten. Wobei das wohl eher für Swift mit der (nicht schön zu benutzenden, aber umfangreichen) iOS-Bibliothek hintendran gilt als für Rust.
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

  • »dot« ist der Autor dieses Themas

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

24

12.05.2016, 14:21

Bingo. Der wirkliche Grund, aus dem die Entwicklung in Java und .Net als so einfach erscheint, liegt in der riesigen Standardbibliothek und den verhältnissmäßig einfachen Möglichkeiten zur Einbindung von Drittbibliotheken (insbesondere letzteres ist leider einer der Schmerzpunkte beispielsweise mit C++). Der Garbage Collector dagegen ist in Wahrheit mehr Fluch als Segen. Ich bin mir sicher, dass kein erfahrener Entwickler ihn vermissen würde, im Gegenteil...

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

25

12.05.2016, 14:30

Zumindest seit es Smart-Pointer gibt ;) Vorher war das schon recht... unschön in C++.
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

  • »dot« ist der Autor dieses Themas

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

26

12.05.2016, 14:45

Nun, Smartpointer gibt es eigentlich schon gleich lang wie C++ ;). Aber zugegeben, ohne Move-Semantik macht das Ganze sehr viel weniger Spaß...

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

27

12.05.2016, 14:53

Einen GC gibt es in Rust übrigens nicht mehr. D baut stark auf dem GC auf. Soweit ich mich erinnere, sind zum Beispiel alle Standard Library Datenstrukturen auf den Garbage Collector angewiesen.

Ich denke es wäre auch falsch zu sagen, dass Garbage Collectoren "die dümmste Idee seit Anbeginn der Informatik" waren. Ich halte es jedoch auch für nicht sehr hilfreich, dass Garbage Collectoren vor einiger Zeit zu einer Grundlage so vieler Sprachen wurde. Java, C#, D, Go, ... Es mag Anwendungsgebiete in denen GCs nützlich sind, aber nicht allgemein, überall, in solchen Sprahcne. Als Grundlage einer Sprache die sich zum Ziel gesetzt hat, einfach und allgemein anwendbar zu sein, ist ein GC meines Erachtens meistens mehr hinderlich. Besitzbeziehungen braucht man trotzdem und sollten besser ausdrückt werden anstatt mehr verschleiert werden. Und der GC geht da einfach, so meine Meinung, in die grundverkerte Richtung für General Purpose Programmiersprachen. Darüberhinaus ist die Freigabe von Ressourcen die nicht nur RAM Speicher sind, mit GCs unmöglich richtig zu lösen. (Hat Dot schon schön dargelegt)

Zitat von »Dot«

Rust hat da imo wesentlich mehr, was man mögen kann. Am Ende haben alle diese Sprachen aber keinen überwiegenden Vorteil gegenüber C++

Du scheinst mit C++ ziemlich glücklich zu sein. Ich bin es ehrlich gesagt nicht. Ich programmiere überwiegend in C++. Ein paar Vorteile von Rust:
  • Keine Header, keine Kopie von Funktionsdeklarationen in Header notwendig.
  • Keine Headereinbindungen notwendig.
  • Rust hat ein traumhaftes Buildsystem. Trotzdem ist es auch noch einfach C Code einzubinden.
  • Durch die funktionalen Ansätze lassen sich viele Dinge viel kompakter ausdrücken. In C++ haben wir <algorithm>. Aber ehrlich: Meistens gibt es genau das was man braucht nicht und viele Dinge sind so umständlich zu benutzen, dass man häufig doch lieber freiwillig darauf verzichtet. Ich hasse das:

    C-/C++-Quelltext

    1
    2
    3
    4
    
    const auto Iter = std::find_if(ThisIsMyVectorObj.cbegin(), ThisIsMyGreatVectorObj.cend(),
         [&](const auto& Item) { return ...; });
    if (Iter != ThisIsMyVectorObj.cend())
        ...

  • Die Ownership Semantik von Rust scheint fantastisch zu sein. Keine Dangling Pointers und sogar Race Conditions. Beides ganz ohne GC! Der Programmierer kann die Intention viel direkter ausdrücken als selbst in C++ mit std::unique_ptr<T>. (Braucht so eine wichtige Klasse wirklich einen langen Namen?)
  • Nie wieder Operator = und Move Konstruktoren für eigene RAII Objekte: Das macht in Rust der Compiler.
  • Keine Integer Typen die zwischen Plattformen unberechenbare Größenänderungen haben. (Oh Gott: long in Windows vs Linux)
  • Gescheite Standardlibrary. Von iostreams (Extrem langsam, sehr kompliziert, hässliche States) über string (Unicode?!?) - alles nicht schön in C++. Schonmal einen eigenen Allocator geschrieben oder Objekte gehabt, die mehr Alignment benötigen?
  • Vereinheitlicht dynamische und statische Polymorphie.
  • Gescheite Macros
  • Compiler Plugins
  • Das Typsystem von Rust scheint ein wenig gewöhnungsbedürftig zu sein. Ich glaube allerdings, dass es auch sehr viel ausdrucksstärker ist.
  • ...
Ich habe in Rust bisher ehrlich gesagt noch nicht so viel gemacht, aber der Sprache möchte ich unbedingt mal einen ernsthaft Versuch geben. Wenn ich in C++ programmiere, habe ich das Gefühl sehr viel Zeit damit zu verbringen, es der Sprache recht zu machen anstatt einfach das programmieren zu können, dass ich wirklich ausdrücken möchte. Andererseits lässt mich die Sprache häufig im Stich wenn Hilfe notwendig wäre.

Ich glaube nicht, dass Rust C++ ersetzen wird. C++ ist einfach ein Platzhirsch mit viel Legacy Code. Aber Rust macht, so mein Eindruck, wirklich erstaunlich viel richtig. Ich denke, dass es für mich schon ein "überwiegender Vorteil" wäre, wenn ich die Sprache einsetzen könnte.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Spiele Programmierer« (12.05.2016, 15:47)


28

12.05.2016, 15:01

Das C++sche Modulsystem, Unicode und Streams sind auf jeden Fall unschön und lästig. Zumindest ersteres soll wohl im kommenden Standard abgelöst werden.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

29

12.05.2016, 15:07

Einen GC gibt es in Rust übrigens nicht mehr.
Sagte ich doch schon, es setzt auf Reference-Counting auf. Ohne gewissenhafte Verwendung von weak/unowned references baut man sich in Rust allerdings sehr schnell den Speicher voll. Die Mittel sind da und sind zum Glück einfach zu verwenden, nur ist es gewöhnungsbedürftig, wenn auch wesentlich weniger gewöhnungsbedürftig (weil gefühlt unnötig [das Gefühl trügt aber eben]) als in C# oder Java. Reference-Count auf 0 heißt auch automatisch Freigabe des Objekts zu diesem Zeitpunkt und nicht erst irgendwann. In C++ ist eine Ownership bei einer Referenz wesentlich schwerer "versehentlich" zu übertragen als dass man bei Rust das weak/unowned vergisst und dann plötzlich eine ungewollte Ownership bekommt. Da ist C++ schon deutlich ausdrucksstärker, wenn auch ulkigerweise impliziter zur gleichen Zeit.
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« (12.05.2016, 15:14)


Wirago

Alter Hase

Beiträge: 1 193

Wohnort: Stockerau

Beruf: CRM Application Manager

  • Private Nachricht senden

30

12.05.2016, 15:44

Die Wahrheit ist eher, dass es sich für die meisten Unternehmen nie lohnen würde C++ zu verwenden. In Java oder C# entwickelt man auf Kosten der Performance wesentlich schneller.


Das ist der springende Punkt. Geschwindigkeitskritische Anwendungen wird keiner in Java schreiben, bei klassischen Businessanwendungen oder Schnittstellen ist es oft egal ob der Vorgang 10 oder 15 Sekunden dauert. Da ist es wichtiger die Software schnell und leicht wartbar zu gestalten. Da macht sich keiner über garbage Gedanken.
Und C# besticht einfach mit .Net und - meiner Meinung nach unterschätztem - Linq

Werbeanzeige