Unterschiede zu C++ für Umsteiger von Java



  • net schrieb:

    ...aber wenn c++ schlau gemacht wär, würde es automatisch nach verlassen des scopes den destruktor aufrufen. macht es aber nicht 😞

    Dann müsste C++ so schlau sein zu ermitteln, ob die Referenz auf ein Heap-Objekt oder auf ein Stack-Objekt zeigt und wenn ersteres, ob noch andere Referenzen drauf zeigen. Dann jedoch sind wir eh wieder bei Java :p

    Also ich würde mich beschweren wenn C++ meine Objekte eigenmächtig killt, nur weil irgendwo eine Referenz ihr Leben aushaucht...



  • Naja, spätestens mit const-Refs dürfte damit aber Schluß sein .

    net schrieb:

    ..aber wenn c++ schlau gemacht wär, würde es automatisch nach verlassen des scopes den destruktor aufrufen. macht es aber nicht 😞

    Entweder Garbage-Collection oder nicht. So eine Mischform geht eben nicht...

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Entweder Garbage-Collection oder nicht. So eine Mischform geht eben nicht...

    warum nicht? könnte man doch in C++ einbauen - einen garbage collector nur für 'heap-referenzen' wie: Class &Object=*(new Class()); das wär doch nicht schlecht, der user hätte freie wahl ob er die eingebaute müllverbrennungsanlage benutzen will, oder C++ wie er's bisher kennt... :xmas2:



  • Dann nimm C++/CLI. Oder warte auf C++0x, da wird noch diskutiert, ob es nicht einen optionalen GC geben soll.



  • Artchi schrieb:

    ...warte auf C++0x, da wird noch diskutiert, ob es nicht einen optionalen GC geben soll.

    ach, das ist schon im gespräch?
    und ich dachte ich muss jetzt 'ne mail an diese standardisierungs-heinis schreiben 😉



  • net schrieb:

    warum nicht? könnte man doch in C++ einbauen - einen garbage collector nur für 'heap-referenzen' wie: Class &Object=*(new Class());

    Randfrage: Woher weiß das System, ob ich gerade eine Heap-Referenz oder eine Stack-Referenz habe? (wenn ich das direkt aufrufe, kann man das ja noch unterscheiden - aber bei einer Anweisung ala Class& ob = func(); siehst du schon nicht mehr, woher die Referenz kommt)



  • CStoll schrieb:

    net schrieb:

    warum nicht? könnte man doch in C++ einbauen - einen garbage collector nur für 'heap-referenzen' wie: Class &Object=*(new Class());

    Randfrage: Woher weiß das System, ob ich gerade eine Heap-Referenz oder eine Stack-Referenz habe? (wenn ich das direkt aufrufe, kann man das ja noch unterscheiden - aber bei einer Anweisung ala Class& ob = func(); siehst du schon nicht mehr, woher die Referenz kommt)

    klar, solche 'gc-aware' referenzen müssten schon eindeutig für's system sein (man könnte ein neues schlüsselwort dafür erfinden z.b. create statt new).
    auch müsste man sicherstellen, dass ein versehentliches 'delete' keine negativen auswirkungen hat... :xmas2:



  • In C++/CLI gibts gcnew als Schlüsselwort, damit in einer Compile-Einheit zwischen verwalteten und nicht verwalteten Code unterscheiden kann:

    Class^ o = gcnew Class(); // GC räumt es nachher weg.
    Class* o2 = new Class(); // Auf dem Heap.
    

    Wenn ein GC in C++ rein kommt, wird man sich bestimmt an C++/CLI orientieren. Da Herb Sutter der Designer von C++/CLI ist und reinzufällig den C++ Komitee Vorsitz inne hat. 😉

    auch müsste man sicherstellen, dass ein versehentliches 'delete' keine negativen auswirkungen hat...

    Wieso? In C++/CLI ist z.B. gerade der Clou das ich auch verwaltete Objekte explizit selbst mit delete zerstören darf. Ist ja alles nur einer Frage des Designs. Dann gibts auch keine Probleme.



  • Artchi schrieb:

    auch müsste man sicherstellen, dass ein versehentliches 'delete' keine negativen auswirkungen hat...

    Wieso? In C++/CLI ist z.B. gerade der Clou das ich auch verwaltete Objekte explizit selbst mit delete zerstören darf. Ist ja alles nur einer Frage des Designs. Dann gibts auch keine Probleme.

    das finde ich schlecht. wenn man die objektlebensdauer selber bestimmen will, dann sollte man die herkömmliche new/delete-logik anwenden. manuelles löschen von GC-verwalteten objekten provoziert doch nur übelste bugs. ich würde beides getrennt halten.



  • net schrieb:

    wenn man die objektlebensdauer selber bestimmen will, dann sollte man die herkömmliche new/delete-logik anwenden. manuelles löschen von GC-verwalteten objekten provoziert doch nur übelste bugs. ich würde beides getrennt halten.

    Richtig. In C++/CLI ruft der delete-Operator bei GC-verwalteten Objekten einfach nur die Dispose Methode auf; die Freigabe des Speichers solcher Objekte bleibt Aufgabe des Garbage-Collectors.

    <a href= schrieb:

    msdn">There is no equivalent function to the C++ delete operator for the CLR.
    ...
    It is, however, illegal to use the delete operator with such a managed, or garbage collected, pointer.
    ...
    In C# you can call the Dispose method directly, or use a using statement just as if the type were defined in C#; but what about C++? How do you normally call the destructor of a heap based object? By using the delete operator, of course! Applying the delete operator to a handle will call the object's Dispose method. Recall that the object's memory is managed by the garbage collector. We are not concerned about freeing that memory, but only about freeing the resources the object contains.



  • Ich mag C++, weil es das macht, was ich ihm sage. Wenn ich sage, er soll das Objekt, welches von einem Zeiger referenziert wird löschen, dann macht er das. Wenn ich das nicht tue, läßt er das bleiben.

    Statt GC und managed-Objects und so etwas kann man Smart-Pointer benutzen. Das erschlägt fast alle Probleme der Objektlebensdauer, wenn man mal Zeiger benutzen muß, was wie bereits festgestellt nicht so häufig vor kommt.

    Ich lege meine Objekte grundsätzlich entweder auf dem Stack an, oder sie werden von einem anderen Objekt, wie z. B. einem Smart-Pointer verwaltet. Dann habe ich keine Probleme mehr mit Memoryleaks. Es gibt ganz wenige Situationen, wo ein GC geholfen hätte (Stichwort: zirkuläre Referenzen). Und bei den wenigen Situationen musste ich mir halt ein wenig Gedanken machen.

    Tntnet



  • Ich denke mal, die Mehrheit hier geht damit konform, das man meistens Stackobjekte nutzt. Wenn man doch mal Objekte mit new anlegen will/muß, gibt es Hilfsmittel (Smartpointer z.B.).

    Einen Vorteil hat aber ein GC: er kann den Speicher fragmentieren. Ich weiß nicht wie das in der Praxis aussieht (ich meine bei Java und .NET). Kann mir das sowohl als Implementierer des GC schwer vorstellen, und wenn es funktioniert, könnte es immense Laufzeitprobleme in dem Moment geben.

    Also, alles hat ein Licht und ein Schatten. Da ist C++ einfach flexibler. Wie TNTNET sagte: ich mach es so, wie ich es will.

    Hier der Vorschlag für einen GC im C++09 (ich schreibe C++09, weil dies das C++ Komitee mittlerweile auch tut, har har har!):
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1943.pdf



  • Artchi: ich klaube du meinste, das der GC den Heap defaragmentieren kann:) der Heap fragmentiert sich quasi von selbst wenn man fröhlich neue objekte anlegt und wieder zerstört 😉

    Ich vermute, das der GC ne interne liste führt, welche die referenzen vom programm-objekten auf die realen Memory-addressen mapped.
    Beim defragmentieren aktuallisiert er halt diese liste.
    Um laufzeit probleme zu verhindern/vermeiden, könnte es sein, daß das programm warten muss, wenn es auf einen referenz zugreifen will, bei dieser der GC grad die reale addresse umschreibt.



  • Simon2 schrieb:

    net schrieb:

    ...
    in java ist das threading aber schon eingebaut. C++ hat auch nix, was dem java keyword 'synchronized' entsprechen würde.
    ...
    * c++ hat keine 'reflection api' (ich weiss, das ist nur was für leute mit schlechtem programmierstil) 😉
    * c++ unterstützt von haus aus keine webtechnologien (wie java mit servlets, applets, jsp, xml, soap...)

    Das fällt alles unter

    Simon2 schrieb:

    ...

    ...

    • Während in Java so ziemlich alles, was "J" im Namen hat, in den Standard aufgenommen hat, sind im C++-Standard nur recht wenige (dafür aber sehr allgemeingültige und wichtige) Dinge festgelegt.

    ...

    "synchronizied" nutzt Dir in enterprise-Umgebungen ebenso wenig wie "von Haus aus webtechnology" und "reflection API" oder die "java-Standard-GUI"...

    Da darfst Du mit dem Zeug dem Framework sowieso nicht "reinpfuschen" ... da ist es einfacher, alles, was der Standard hergibt, verwenden zu können (wie in C++) als nur Teile davon.
    Wie gesagt: C++ ist ein "schmaler Standard" (aber dafür ein sehr stabiler) - für alles, was man in Java macht, gibt's auch C++-Libs.

    Gruß,

    Simon2.

    Das was du mit Reflection in Java machen kannst, geht in C++ einfach nicht. Versuch doch mal in C++ von einer unbekannten Klasse z.B. eine XML Darstellung oder sowas zu erzeugen. Also variablenname1 = wert ...

    Und die C++ Standard Lib. ist nun wirklich nicht toll. Schau dir doch nur mal die std::strings an und versuch dann was mitdem UTF-8 Format zu machen.

    Einen Hirsch für dich :xmas2:



  • Ein GC kann schon nette Dinge bieten, wie Heap Defragmentierung, Verzögertes löschen (sprich man löscht, wenn man Resourcen braucht oder man gerade keine Last auf dem System hat), Freigabe zyklischer Referenzen.

    Aber was ein GC nicht kann: Destruktoren. Das macht einen GC leidersehr unhandlich, wenn man ihn zB mit Dingen wie Exceptions kombinieren will.

    btw. Ich hab mir mit C++/CLI nicht intensiv befasst, aber das was mir Vinzenz mal gezeigt hat, finde ich äußerst schrecklich. Kaum zu glauben, das Herb Sutter das entworfen haben soll. Seit dem empfehle ich übrigens lieber gotw zu lesen, als seine Bücher zu kaufen 🙂



  • ManOMan schrieb:

    ...Versuch doch mal in C++ von einer unbekannten Klasse z.B. eine XML Darstellung oder sowas zu erzeugen. ...

    ManOMan schrieb:

    ...Und die C++ Standard Lib. ist nun wirklich nicht toll. Schau dir doch nur mal die std::strings an und versuch dann was mitdem UTF-8 Format zu machen....

    Und wogegen oder wofür soll das ein Argument sein ?

    Gruß,

    Simon2.

    BTW: Die Tatsache, das std::string nicht ideal für UTF-8 ist, bedeutet für mich noch nicht, dass die STL "nicht toll" sei. Seltsamerweise ist mir bislang noch NIE UTF-8-Programmierung (weder in Java noch in C++) begegnet...kenne das bestenfalls im "Webzeug" - und das ist sowieso "weggekapselt".



  • Oh waier! UTF-8! Ich habe mich ja letztens damit beschäftigt (falls sich jemand an meinen Thread erinnern kann?), mit Unicode & Co. Wenn man das nicht macht, unterliegt man leider immer dieser UTF-8-Mystik. Und man meint, UTF-8 ist zu Runtime wichtig. Nichts da! Wenn man sich das genau anschaut, wird man sogar feststellen, das UTF-8 zur Runtime in gewisserweise kontraproduktiv ist (Performance!!!).

    WinNT, Unix, Solaris und Java arbeiten alle mit UTF-16-Strings!!! Java 1.5 ist angeblich (hat mir ein Arbeitskollege erzählt, habe ich nicht selber nachgeschaut) zur Runtime sogar auf UTF-32 umgestiegen.

    Fakt ist aber, das die meisten Systeme ihre Strings mit UTF-16 repräsentieren. Und std::wstring erfüllt diesen Zweck hervorragend. UTF-8 und andere Codings (und das ist der springende Punkt!!!) werden erst dann wichtig, wenn ich meine Strings mit anderen Systemen (egal welche, ob Remote oder Lokal) oder Programmen austauschen will. Dann muß ich fähig sein, notfalls von UTF-16 auf z.B. UTF-8 zu konvertieren. Und selbst das ist laut unicode.com-FAQ nicht eine Patentlösung, weil es verschiedene UTF-8 Präsentierungen gibt:
    http://www.unicode.org/faq/utf_bom.html#31

    std::string die UTF-8-Unfähigkeit anzulasten, ist falsch. Weil std::string ein ASCII-String ist, und ich für Internationalisierung std::wstring benutzen kann.
    Wenn ich Strings über das Internet schicken will, oder als XML-Value schreiben will, muß ich nur in dem Moment eine wstring to UTF-8-Konvertierung nutzen. Und die gibt es zu Hauf im Netz runter zu laden: ICU (IBM) und xstring (Adobe) bieten opensource-Libs für Konvertierungen an. Dinkumware hat sogar eine auf LocaleFacet-Ebene die sich transparent in die C++ Streams einklinkt.

    Achja, das einzige mir pers. bekannte System bzw. OS welches UTF-8 zur Laufzeit benutzt, ist Linux. Aber das kann einen std::wstring-Nutzer auch nicht kratzen, denn die Konvertierung nach UTF-8 muß die genutzte API in einer Blackbox unterstützen. Würde C++ einen UTF-8-String anbieten, müsste die Konvertierung für Unix, Solaris, WinNT usw. wieder stattfinden. Egal wie man es dreht und wendet, einer muß immer Konvertieren.



  • Simon2 schrieb:

    ManOMan schrieb:

    ...Versuch doch mal in C++ von einer unbekannten Klasse z.B. eine XML Darstellung oder sowas zu erzeugen. ...

    Und wogegen oder wofür soll das ein Argument sein ?

    Das soll dir zeigen, dass man Reflection nicht mit irgendeiner Lib in C++ nachbauen kann.

    Artchi schrieb:

    std::string die UTF-8-Unfähigkeit anzulasten, ist falsch. Weil std::string ein ASCII-String ist, und ich für Internationalisierung std::wstring benutzen kann.
    Wenn ich Strings über das Internet schicken will, oder als XML-Value schreiben will, muß ich nur in dem Moment eine wstring to UTF-8-Konvertierung nutzen. Und die gibt es zu Hauf im Netz runter zu laden: ICU (IBM) und xstring (Adobe) bieten opensource-Libs für Konvertierungen an.

    Ja genau das ist es was mich unter anderem an der STL stört, es gibt nicht einen string für alles wie in Java, sondern um z.B. UTF-8 verwenden zu können, brauch ich schon wieder einen anderen
    Ich hab dann auch mit wstrings hinundher konvertiert. Was du mit "zur Laufzeit" willst ist mir schleierhaft, wenn ein Programm einen string in utf-8 habenm will, dann muss ich halt konvertieren.



  • Was du mit "zur Laufzeit" willst ist mir schleierhaft

    Eben, du weißt nicht was "Laufzeit" ist. Dann würdest du nicht sagen, das Java alle möglichen Strings abdeckt.

    es gibt nicht einen string für alles wie in Java

    Java hat nur EINEN Laufzeit-String, und das ist ein UTF-16-String!!! Nichts mit "alles abdecken"! Wenn du UTF-8-XML rausschreibst, konvertiert die XML-Library die Java-UTF-16-Strings für den einen Moment nach UTF-8. Wenn du einen XML-UTF-8-Value in einen Java-String lädst, ist der ehem. UTF-8-String zur Java-Laufzeit ein UTF-16-String.

    Wenn die C++-Leute lieber std::string und nicht std::wstring benutzen, dann kann C++ nichts dafür. wstring ist das C++-Pendant zum Java-String. Ich benutze nur noch std::wstring, und für rein technische Zeichenketten vielleicht std::string.

    wenn ein Programm einen string in utf-8 habenm will, dann muss ich halt konvertieren.

    Javas String kann bzgl. Unicode nicht wirklich mehr als wstring. Oder zeig mir bitte wo java.lang.String eine UTF-8-Konvertierung anbietet???



  • Hallo,
    UTF-8 ist ein Kompressionsformat für Unicode. Der Trick dabei ist, daß alle ASCII-Zeichen (0 - 127) unkomprimiert gespeichert werden. Wenn Linux intern UTF-8 verwendet, dann ist das kein großer Nachteil, da bei ASCII-Zeichen nichts dekodiert werden muß und daher auch keine Nachteile zur Laufzeit auftreten.

    Außerdem kann man mit UTF-8 wesentlich mehr Zeichen speichern, als mit dem primitiven UTF-16 Format.


Anmelden zum Antworten