Wann sollte ich C# über C++11 benutzen?



  • kantaki schrieb:

    Ich programmiere jetzt seit ca 2 Jahren. Angefangen habe ich mit Java -> C# -> Python -> Scala -> c++11

    Ich war immer der Meinung das man mit C# viel produktiver ist als mit C++. Doch vor 2 Monaten habe ich angefangen C++11 zu lernen und es ist ganz anders als ich es mir vorgestellt habe.

    Nach zwei Jahren in C++ Vorteile zu entdecken halte ich schon für recht gut. Das dauert üblicherweise länger.

    kantaki schrieb:

    Manual memory management mit smart pointern ist nicht wirklich mehr Aufwand als automated memory management.
    Vielleicht gibt es Bereiche in denen eine GC nützlicher ist?

    Ich finde den Aufwand teilweise deutlich größer als in C#/Java. Den GC braucht man allerdings nicht, um qualitative Software zu schreiben.

    Aktuell programmiere ich in Python, wo ich anfangs extrem produktiv startete, aber die Sprache semantisch schnell zurück bleibt. Sie erlaubt mir also Fehler zu machen, ohne dass ich das mitbekomme. Das Problem gibt es auch in Java und C# - auch in C++ natürlich, aber C++ liefert da einiges mehr als die vorgenannten. Das fängt den Mehraufwand durch die manuelle Speicherverwaltung deutlich auf.
    Dafür muss man allerdings mehr lernen. Für kleine Hobbyprojekte reicht Java und C# wunderbar.
    Für alles was mehr ist... würde ich davon abraten.

    kantaki schrieb:

    Zu meiner eigentlichen Frage:

    Wann sollte ich C# über C++ benutzen? In welchen Bereichen hat C# seine stärken? (Gegenüber c++)

    Die mitgelieferten Frameworks muss man nicht nachträglich installieren, sondern man kann sie direkt nutzen.
    Wenn Du eine billige GUI brauchst, bietet sich WinForms an.

    Ich sehe C# als eine Art Skriptsprache zwischen den bekannten Skriptsprachen und C++. Es ist eine gute und durchaus schnelle Sprache. Aber wenn man's richtig machen will, wenn man mehr machen will als Algorithmen, die Fließband-Aufgaben erledigen, dann bin ich schnell bei C++. Wenn ich ein Projekt in einer Größe aufbaue, dass ich es nicht alleine überblicken kann, dann brauche ich C++ und die Features, die man in C# zur Vereinfachung weggelassen hat.

    Ein GC braucht eigentlich kein Mensch. Im Schnitt meldet valgrind alle 3-6 Monate mal ein Leak, welches ich mir was angucken sollte. Dann mache ich das und dann war's das.



  • Xin schrieb:

    Ein GC braucht eigentlich kein Mensch. Im Schnitt meldet valgrind alle 3-6 Monate mal ein Leak, welches ich mir was angucken sollte. Dann mache ich das und dann war's das.

    Man brauchts nicht, weil men es als C++ Programmierer eben gewohnt ist, seinen Code ohne GC zu programmieren.
    Der unberechtigten Ban war übrigens fehl am Platz.



  • Bei C++ brauchst du halt sehr lange, bis du die Sprache wirklich effizient einsetzen kannst. D.h. du kennst nicht nur die Sprachmittel, sondern auch Idiome und kannst die verschiedenen Abstraktionsmöglichkeiten kombinieren. Ich würde mal behaupten, der durchschnittliche C++-Programmierer ist nicht so weit. Typischer C++-Code ist daher tendenziell eher kompliziert und erweckt den Eindruck, man müsse viele Low-Level-Arbeiten selbst erledigen.

    Wenn du C++ jedoch gut beherrschst, hast du in mächtiges Werkzeug zur Hand, mit dem du in kurzer Zeit viel erreichen kannst.

    Xin schrieb:

    Das fängt den Mehraufwand durch die manuelle Speicherverwaltung deutlich auf.

    Was für einen Mehraufwand? Wenn du in C++ manuell Speicher verwaltest, hast du was Grundsätzliches nicht verstanden.



  • Lightspeed=>C++ schrieb:

    Xin schrieb:

    Ein GC braucht eigentlich kein Mensch. Im Schnitt meldet valgrind alle 3-6 Monate mal ein Leak, welches ich mir was angucken sollte. Dann mache ich das und dann war's das.

    Man brauchts nicht, weil men es als C++ Programmierer eben gewohnt ist, seinen Code ohne GC zu programmieren.

    Damit meine ich nicht die Gewohnheit, sondern die Notwendigkeit.
    Geschätzt 90% bei der Speicherveraltung lassen sich mit C++ besser lösen als mit Java/C# und dem GC. Beim Rest muss man sich wirklich fragen, ob man dafür so ein Ungetüm haben will.
    Ich bin der Meinung, dass das kein Mensch braucht.

    Lightspeed=>C++ schrieb:

    Der unberechtigten Ban war übrigens fehl am Platz.

    Ban? Worum geht's und müsste ich was davon wissen?

    Nexus schrieb:

    Xin schrieb:

    Das fängt den Mehraufwand durch die manuelle Speicherverwaltung deutlich auf.

    Was für einen Mehraufwand? Wenn du in C++ manuell Speicher verwaltest, hast du was Grundsätzliches nicht verstanden.

    Tja, dann habe ich wohl was Grundsätzliches nicht verstanden.
    Ich löse in erster Linie Probleme mit C++ und da gehören auch teilweise manuelle Speicherorganisation dazu. Kann aber auch sein, dass ich andere Probleme als Du löse.



  • Xin schrieb:

    Ich löse in erster Linie Probleme mit C++ und da gehören auch teilweise manuelle Speicherorganisation dazu. Kann aber auch sein, dass ich andere Probleme als Du löse.

    Ein Beispiel?



  • volkard schrieb:

    Xin schrieb:

    Ich löse in erster Linie Probleme mit C++ und da gehören auch teilweise manuelle Speicherorganisation dazu. Kann aber auch sein, dass ich andere Probleme als Du löse.

    Ein Beispiel?

    ...entweder verstehe ich hier gerade "manuelle Speicherorganisation" nicht, aber ich brauche wohl kaum ein Beispiel für new und delete zu geben!?

    Ansonsten habe ich durchaus auch Container, die als MemoryPools dienen und über Placement-New Objekte konstruieren.

    SmartPointer sind kein GC, zumal sie nicht in der Sprache verankert sind, ergo die Datentypen aufwendiger zu repräsentieren sind, ergo der Code unleserlicher wird. => Mehraufwand.



  • Ich persönlich verwend C# wenn ich schnell irgendein Tool mit UI basteln möchte, da sowas mit C# tatsächlich sehr einfach und schnell geht. Die Erfahrung lehrt mich allerdings, meine Anwendungen so zu bauen, dass die eigentliche Funktionalität in Form einer C++ Library implementiert wird und das C# UI lediglich eine dünne Schicht oben drüber ist, die einfach die richtigen Knöpfe auf der Library drückt. Ich find C# ist eine sehr praktische Sprache, aber für Dinge wie die einigermaßen effiziente Implementierung komplexer Datenstrukturen oder gar Ressourcenverwaltung leider eher ungeeignet. Und wesentlicher Grund dafür ist unter anderem genau die Garbage Collection, welche imo der fundamentale Schwachpunkt von Sprachen wie C# und Java ist, da Garbage Collection den Umgang mit Ressourcen ohne zu leaken einfach nur unvorstellbar schwer macht. Ja, man muss sich nicht mehr darum kümmern, dass jedes new sein passendes delete hat. Aber der Preis den man dafür zahlt, nämlich dass die Verwaltung jeder anderen Art von Ressource (selbst von so trivialen und allgegenwärtigen Dingen wie Dateien) zur Sisyphusarbeit wird, ist imo nicht zu rechtfertigen. Garbage Collection ist imo gut gemeint, geht das Problem aber vom völlig falschen Standpunkt aus an. Ich finde aber die Kombination von C# und C++ sehr mächtig, was allerdings vor allem daran liegt, dass es leider kein brauchbares UI Toolkit für C++ gibt, wobei es mit Windows 8 da imo einen schwachen Schimmer der Hoffnung am Horizont gibt. Der große Vorteil von C# gegenüber C++ ist die einfach nur riesige Library, die einem mit dem .NET Framework zur Verfügung steht. Rein sprachlich hat C# den Vorteil, dass es vergleichsweise einfach ist, was es zu meiner üblichen Empfehlung für Anfänger macht, hat aber eben auch fundamentale Schwächen, die den potentiellen Nutzen der Sprache am Ende imo leider stark einschränken.

    Zusammenfassung: Wenn es etwas vergleichbares wie das .NET Framework für C++ gäbe, würde ich keinen Gedanken an C# verschwenden. Leider gibt es sowas im Moment aber nicht und das nächstbeste ist die Kombination von C# und C++...



  • Xin schrieb:

    ...entweder verstehe ich hier gerade "manuelle Speicherorganisation" nicht, aber ich brauche wohl kaum ein Beispiel für new und delete zu geben!?

    Doch, und zwar eines das man nicht trivial mit einem STL-Container lösen kann, dessen weglasen dir bei der nächsten Gelegenheit in den Fuß schießt.



  • @Dot: ich weiß nicht, wo du da jetzt Probleme siehst. Ich hab mehrere Jahre als C# Entwickler gearbeitet und wir haben tatsächlich auch einigermaßen größere Programme damit entwickelt und hatten keine Probleme. Weder mit der Performance, der Effizienz noch sonst was. Auch Resourcenverwaltung ist kein Problem.
    Man darf gern C++ mögen und damit arbeiten, aber ich finds etwas unfair und weltfremd, wenn man anfängt zu argumentieren, es wäre schwer oder unmöglich in C# effizient mit Ressourcen zu arbeiten, oder der GC würde stören oder ähnliches. Zu 99,999% merkst du davon absolut rein gar nichts und brauchst dir darum überhaupt keine Gedanken zu machen. Und in C# using zu benutzen ist nicht wirklich umständlicher als in C++ einen smart pointer zu benutzen.



  • otze schrieb:

    Xin schrieb:

    ...entweder verstehe ich hier gerade "manuelle Speicherorganisation" nicht, aber ich brauche wohl kaum ein Beispiel für new und delete zu geben!?

    Doch, und zwar eines das man nicht trivial mit einem STL-Container lösen kann, dessen weglasen dir bei der nächsten Gelegenheit in den Fuß schießt.

    Ich habe mal kurz überlegt, ob ich hierauf noch antworten will.

    Eigentlich nicht, aber ich denke, Du darfst Dir durchaus bewusst werden, dass "Doch" schonmal unpassend ist: Ich brauche nicht und zum anderen habe ich bereits.
    Wenn Du für new und delete keine Verwendung hast, dann herzlichen Glückwunsch, dann solltest Du Dich nicht mit Anfängern wie mir abgeben, sondern Herrn Stroustrup mal eine Mail schreiben, dass er diese Operatoren entfernen möge.

    Ich bin immer wieder erstaunt, wieviele Leute sich hier Sorgen um meine Füße machen. Sorgt euch nicht, ich programmiere schon ein, zwei Jahre und meinen Füssen geht es wunderbar.



  • Ich sehe IDisposable als Symptom und using als Symptombehandlung und nicht als tatsächliche Problemlösung. using ist am Ende nur Syntaxzucker für genau einen konkreten Anwendungsfall, nämlich den einer temporären Ressource in einer Funktion. Zugegeben: Für den Fall funktioniert es. Aber leider deckt das eben auch nur einen Bruchteil des Problems ab. IDisposable ist genau das, was man sich mit Garbage Collection einhandelt. Das Grundproblem mit IDisposable ist, dass es ansteckend ist. Sobald du irgendwo in einer Objekthierarchie ein IDisposable einbaust, musst du sämtliche Objekte weiter oben ebenfalls IDisposable machen. Mit anderen Worten: Du hast mit einem Schlag einen riesen Haufen Code der sich plötzlich um das Management der Lebensdauer eines einzigen Members einer einzigen Klasse irgendwo ganz weit unten kümmern muss. Etwas, das eigentlich als Implementierungsdetail in einer Klasse gekapselt sein sollte, muss plötzlich in Code, der eigentlich nichts damit zu tun haben sollte, berücksichtigt werden. Und auf dieses Problem stoßt man leider sehr schnell. Schonmal eine Klasse geschrieben, die z.B. eine Datei als Member haben sollte, die so lange offen sein soll, wie das Objekt benutzt wird? In C++ geht das völlig natürlich ohne dass ich auch nur irgendwas dafür tun müsste. In C# muss ich dafür nicht nur extra Code schreiben, sondern potentiell auch noch über das ganze Programm verteilt sehr viel dem eigentlichen Problem völlig fremden Code seiner Lesbarkeit berauben...



  • Xin schrieb:

    ...entweder verstehe ich hier gerade "manuelle Speicherorganisation" nicht, aber ich brauche wohl kaum ein Beispiel für new und delete zu geben!?

    Das Problem ist: new und delete gehören nicht in den Anwendercode. Sie sind sinnvoll, da du mit ihnen eine einfache Möglichkeit zur Speicherverwaltung hast, aber ihre Verwendung gehört immer abgekapselt.

    Xin schrieb:

    SmartPointer sind kein GC, zumal sie nicht in der Sprache verankert sind, ergo die Datentypen aufwendiger zu repräsentieren sind, ergo der Code unleserlicher wird. => Mehraufwand.

    Ne. Der Mehraufwand ist bedeutungslos, wenn man beachtet, wie viel Logikcode durch RAII wegfällt. Du hast nachher kein einziges delete mehr. Funktionen mit mehreren Rückgabepfaden oder Exceptions sind automatisch sicher und werden nicht mit Aufräumcode unleserlich gemacht.

    Simples Beispiel:

    // RAII
    std::unique_ptr<T> ptr(new T);
    ptr->func();
    if (ptr->ok())
        return ptr->thing();
    else
        return 47;
    
    // Manuelle Speicherverwaltung
    T* ptr(new T);
    ptr->func(); // func() darf nicht werfen
    if (ptr->ok()) // ok() darf nicht werfen
    {
        int r = ptr->thing(); // thing() darf nicht werfen
        delete ptr;
        return r;
    }
    else
    {
        delete ptr;
        return 47;
    }
    

    Nun stell dir das Gleiche vor mit mehr als einer Ressource. Oder, falls die einzelnen Funktionsaufrufe Exceptions werfen können. Der Code wird wahnsinnig unübersichtlich mit manueller Speicherverwaltung.

    Nene, RAII ist immer besser. Und Smart-Pointer nicht zu benutzen wegen syntaktischem "Mehraufwand" ist doch etwas sehr fragwürdig. Gerade wenn sie Null Laufzeitkosten haben.



  • dot schrieb:

    Sobald du irgendwo in einer Objekthierarchie ein IDisposable einbaust, musst du sämtliche Objekte weiter oben ebenfalls IDisposable machen. Mit anderen Worten: Du hast mit einem Schlag einen riesen Haufen Code der sich plötzlich um das Management der Lebensdauer eines einzigen Members einer einzigen Klasse irgendwo ganz weit unten kümmern muss. Etwas, das eigentlich als Implementierungsdetail in einer Klasse gekapselt sein sollte, muss plötzlich in Code, der eigentlich nichts damit zu tun haben sollte, berücksichtigt werden. Und auf dieses Problem stoßt man leider sehr schnell. Schonmal eine Klasse geschrieben, die z.B. eine Datei als Member haben sollte, die so lange offen sein soll, wie das Objekt benutzt wird? In C++ geht das völlig natürlich ohne dass ich auch nur irgendwas dafür tun müsste. In C# muss ich dafür nicht nur extra Code schreiben, sondern potentiell auch noch über das ganze Programm verteilt sehr viel dem eigentlichen Problem völlig fremden Code seiner Lesbarkeit berauben...

    Ja, das stimmt schon. Das ist ein technisches Problem. Aber ich sehe so gut wie keine Use Cases für sowas und keine praktischen Probleme. Wenn eine Klasse intern Ressourcen verwaltet, ist es selbst eine Ressource und es macht auch Sinn, dass sie IDisposable implementiert. Und brauchen tut man das ganz ganz selten. Ich hab sicher schon mal Klassen geschrieben, die eine Datei oder andere Ressource offen halten, auch wenn ich mich grad nicht explizit dran erinnern kann und das sicherlich extrem selten vorkam. Aber das war sicher nichts, wo ich 10 000 von solchen Objekten im Programm verwalte. Das war dann vielleicht mal eine Klasse, die eine Datei offen gehalten hat, mein Gott, dann wird die notfalls halt etwas später zugemacht. Ich halte diese ganzen Probleme für nicht wirklich praxisrelevant.



  • Ich denke mal Mechanics wird von Microsoft gesponsert und will jetzt künstlich die Probleme kleinreden.



  • Nexus schrieb:

    Xin schrieb:

    ...entweder verstehe ich hier gerade "manuelle Speicherorganisation" nicht, aber ich brauche wohl kaum ein Beispiel für new und delete zu geben!?

    Das Problem ist: new und delete gehören nicht in den Anwendercode. Sie sind sinnvoll, da du mit ihnen eine einfache Möglichkeit zur Speicherverwaltung hast, aber ihre Verwendung gehört immer abgekapselt.

    "Anwendercode"?

    Wer ist denn hier bitte Anwender!?
    Der Entwickler als Anwender der Programmiersprache? Und der soll kein new und delete mehr anwenden?
    Wer dann?

    Nexus schrieb:

    Xin schrieb:

    SmartPointer sind kein GC, zumal sie nicht in der Sprache verankert sind, ergo die Datentypen aufwendiger zu repräsentieren sind, ergo der Code unleserlicher wird. => Mehraufwand.

    Ne. Der Mehraufwand ist bedeutungslos, wenn man beachtet, wie viel Logikcode durch RAII wegfällt. Du hast nachher kein einziges delete mehr. Funktionen mit mehreren Rückgabepfaden oder Exceptions sind automatisch sicher und werden nicht mit Aufräumcode unleserlich gemacht.

    Dann möchte ich sehen, wie Du eine Liste in RAII implementiert.
    Und jetzt sag nicht "Ich nutze std::list"...

    Nexus schrieb:

    Nene, RAII ist immer besser. Und Smart-Pointer nicht zu benutzen wegen syntaktischem "Mehraufwand" ist doch etwas sehr fragwürdig. Gerade wenn sie Null Laufzeitkosten haben.

    Ahja... wir haben hier eine Pseudodiskussion. Lies mein erstes Posting, bevor Du Dich auf einen Zug von otze und volkard schwingst.

    Du nennst es syntaktischen Mehraufwand für SmartPointern im Vergleich zum GC. Ich spreche von Mehraufwand. Wir sprechen also beide von Mehraufwand. Wir sollten nicht über Dinge argumentieren, wo wir uns einig sind.
    Ich habe nirgendwo geschrieben, dass ich gegen die Verwendung von SmartPointern bin oder gegen RAII Partei mache.

    Dass ein Smartpointer Null Laufzeitkosten hat, wäre mir allerdings neu. Deine Behauptung an Unique-Pointern festzuhalten ist nämlich etwas mutig. Manuelle Speicherverwaltung braucht man nämlich nicht für gezeigtes Beispiel eines UniquePointers. Für Dein Beispiel ist ... eher unangebracht für manuelle Speicherverwaltung. Es geht nicht darum ein delete zu vermeiden. Für die Argumentation wäre vielleicht ein Beispiel sinnvoll, was überhaupt ein new benötigt.

    // scheiß was auf Pointer.
    T obj;
    obj.func();
    if (obj.ok())
        return obj.thing();
    else
        return 47;
    

    Schreib eine doppelt verkettete Liste mit SmartPointern ohne Mehraufwand in Syntax und Rechenleistung. Syntaktisch ist da ist die GC vorne, womit der C# Code hier lesbarer ist. Mehr habe ich nie gesagt.



  • Mechanics schrieb:

    Das ist ein technisches Problem.

    ...dessen Existenz notwendige Konsequenz der Verwendung von Garbage Collection ist...

    Mechanics schrieb:

    Aber ich sehe so gut wie keine Use Cases für sowas und keine praktischen Probleme.
    [...]
    Und brauchen tut man das ganz ganz selten. Ich hab sicher schon mal Klassen geschrieben, die eine Datei oder andere Ressource offen halten, auch wenn ich mich grad nicht explizit dran erinnern kann und das sicherlich extrem selten vorkam. Aber das war sicher nichts, wo ich 10 000 von solchen Objekten im Programm verwalte.

    Nur weil du etwas ganz ganz selten brauchst, heißt das noch lange nicht, dass man etwas ganz ganz selten braucht. Ich weiß ja nicht was für Anwendungen du so schreibst, aber meiner Erfahrung nach braucht man das in spätestens jeder nichttrivialen Anwendung früher oder später. Schonmal versucht z.B. OpenGL in C# zu verwenden? Ich hab mir auch gedacht, dass es so schlimm ja nicht sein kann. Und das war genau der Fehler, der mich damals eines Besseren belehrt hat. Und dabei was das sogar noch eine relativ einfache Anwendung...

    Mechanics schrieb:

    Wenn eine Klasse intern Ressourcen verwaltet, ist es selbst eine Ressource und es macht auch Sinn, dass sie IDisposable implementiert.

    Stimmt, wenn man IDisposable als gegeben annimmt, wozu C# dich offenbar erzogen hat. Denn in der Welt von C# gibt es tatsächlich keine Alternative (genau das ist ja der Kern meiner Kritik). Aber überleg dir mal, ob du nicht vielleicht völlig anders denken würdest, wenn du, selbst nur für einen kurzen Moment, schonmal eine bessere Welt gesehen hättest...

    Mechanics schrieb:

    Das war dann vielleicht mal eine Klasse, die eine Datei offen gehalten hat, mein Gott, dann wird die notfalls halt etwas später zugemacht. Ich halte diese ganzen Probleme für nicht wirklich praxisrelevant.

    Du hast dich sicher auch schon mehr als einmal drüber geärgert, dass du z.B. eine Datei nicht umbenennen, löschen etc. konntest, weil irgend ein anderer Prozess sie blockiert hatte? Genau diese Einstellung beschert uns derartige Software...



  • Ich wollte hier eigentlich keinen Krieg auslösen :).

    Ich lese oft das C# sehr gut in Verbindung mit GUI's sein soll. Doch niemand hier hat Qt genannt. Ich habe mit beiden GUI solutions gearbeitet und ich bin nicht wirklich langsamer mit C++ & Qt als mit C# WPF.

    Den richtigen Vorteil von C# sehe ich immer noch nicht. Compile speed, kickass IDE support , huge library, interop mit anderen .NET Sprachen sind nice to have aber überzeugen mich nicht wirklich diese Sprache einzusetzen.

    Wahrscheinlich ist es wohl doch eine reine Geschmackssache.



  • Wenn man bei Qt mal unter die Haube schaut, vergeht einem das Lachen in Anbetracht der Hässlichkeiten, die einem da entgegen starren, leider sehr schnell. Die Tatsache, dass Qt vermutlich praktisch das beste ist, was es für C++ im Moment gibt, stimmt mich immer leicht depressiv...



  • Warum interessiert dich das so stark was unter der Haube abgeht? So lange es nicht buggy ist, sollte es doch egal sein.



  • Weil ich persönlich großen Wert auf Ästhetik lege.


Anmelden zum Antworten