Erst C oder gleich C++ ???



  • ~~fricky schrieb:

    Sollte man innerhalb einer Klasse einmal unartig sein und einen nakten Zeiger auf ein Heap-Objekt verwalten, so ist es wirklich kein Akt ein delete in den Destruktor zu schreiben.
    Es ist ungfähr so schwierig wie das Schuhe binden nach dem Schuhe anziehen.

    Aber nicht den Kopierkonstruktor und den Zuweisungsoperator vergessen.



  • Shade Of Mine schrieb:

    Ich kenne nur die closures in c++ und die haben eigentlich kein ref counting dabei...

    Dafür aber manuelles Speichermanagement. Natürlich kann man sich das mit Smart-Pointern o.ä. vereinfachen - aber das ist auch wieder eine GC-Variante.

    Oder falls du __closure in C++Builder meinst: das ist eine retrospektiv als unglücklich einzuschätzende Wortwahl, hat aber mit den anonymen Methoden von Delphi 2009, besser bekannt als Closures, nicht das Geringste zu tun.

    Shade Of Mine schrieb:

    Sicher, aber ich dachte dir geht es um default cctors...

    Was auch immer. Das komplette "Jedes struct ist jetzt eine Klasse" inklusive aller Implikationen, eine davon z.B. Default-, Kopierkonstruktor und Zuweisungsoperator für alle Klassen, ist ein gewaltiger Designfehler - IMHO.

    Shade Of Mine schrieb:

    der artikel ist doof

    Du bist unqualifiziert.

    Shade Of Mine schrieb:

    sag einfach was du daraus meinst. mag nicht den ganzen artikel zerpflücken müssen.

    Brauchst du gar nicht. Er ist eigentlich, von der Einleitung abgesehen, recht fixiert auf das Thema, das ich ansprach. Wieso soll ich das jetzt nochmal erklären?

    Shade Of Mine schrieb:

    das ist eine zusatz information die delete nicht braucht -> du sparst performance

    Abstrus.

    Der tatsächliche Grund dürfte sein, daß new[] erst nach new eingeführt wurde und man vermutlich irgendein ABI nicht kaputtmachen wollte.



  • Tachyon schrieb:

    Mir fallen da jede Menge Dinge in C ein, die unsicher sind. Das fängt schon beim printf/scanf an, geht über das gesamte Bastelei mit Strings und Arrays bis hin zu so tollen Sachen wie die wenigen Standardalgorithmen die absolut 0 Typsicherheit bieten.

    Was haben diese Dinge dann in einer angeblichen High-Level-Sprache wie C++ zu suchen?

    Man muss eben wissen, was man tut. Das gilt, wer hätte das gedacht, auch für C++, Ada und alle möglichen anderen Sprachen.

    Eine vernünftige Sprache konzentriert sich auf bestimmte Konzepte und abstrahiert von den Details darunter. Wenn ich in C programmiere, brauche ich mich z.B. nicht darum zu kümmern, welche Register jetzt wohinaddiert werden.

    In C braucht es Disziplin um was Ordentliches zu Stande zu bringen. In C++ muss man sich von alten Strukturen lösen und auf C++-Konstrukte umsatteln.

    Man kann sich beim Umstieg von C auf C++ eben nicht von irgendwas lösen, denn die Low-Level-Probleme sind immernoch da. Man bekommt nur noch mehr Probleme dazu.

    Dann ist C++ auch einfacher als C.

    lol



  • Tachyon schrieb:

    ~fricky schrieb:

    ...

    Ist klar, Du greifst Dir den Teil der offensichtlich pure Ironie war, und gehst auf die ernst gemeinten Aussagen nicht ein.

    ach so, du bist also selbst der meinung, dass c++ viele wacklige konstrukte hat. gut, dann hab' ich nichts gesagt.
    🙂



  • namespace invader schrieb:

    Tachyon schrieb:

    Mir fallen da jede Menge Dinge in C ein, die unsicher sind. Das fängt schon beim printf/scanf an, geht über das gesamte Bastelei mit Strings und Arrays bis hin zu so tollen Sachen wie die wenigen Standardalgorithmen die absolut 0 Typsicherheit bieten.

    Was haben diese Dinge dann in einer angeblichen High-Level-Sprache wie C++ zu suchen?

    Zu der Zeit wo C++ entwickelt wurden ist, war es ein Argument das die C-Bibliotheken auch unter C++ laufen. Aber: Nur weil etwas noch möglich ist, heißt das nicht, das man dies auch verwenden sollte (bzw. man sollte seinen Kopf vorher einschalten). Wobei dies für alle mir Bekannten Sprachen gilt: Man kann vieles falsch verwenden, ob nun in C++, Java, C# oder anderen Sprachen.

    Es gibt genauso gründe für die Sprache C++ wie für fast alle anderen Sprachen, ansonsten schaut euch mal bitte Projekte an: Wenn C++ ach soooo schlecht ist, sagt mir mal warum es sich wie C noch immer hält?

    C++ hat (wenn man nicht auf die C-Relikte zugreift) mehr Sicherheit als C - und viele (nicht alle) Probleme von C sind behoben (manches dadurch erkauft man durch eine größere Runtimeumgebung, anderes durch eine höhere Komplexität [Templateklassen] - wobei hier zwischen Verwenden und selbst programmieren noch gewaltige Unterschiede liegen).

    Wie wäre es aber mal wieder zum Thema zurück zu kehren: Die Frage ist nicht ob C bzw. C++ schlecht ist (verwendet es nicht, wenn ihr es nicht wollt), sondern ob man erst C oder gleich C++ lernen soll. Und hierbei ist meine Meinung: Wenn jemand C++ lernen will, ist es unsinnig auch noch C vorher zu lernen, wenn er letzteres Tatsächlich braucht, kann er dies später immer noch aneignen.

    cu André



  • Man kann nicht C++ ohne C lernen, es sei denn, man will nur eine Teilsprache von C++ lernen.

    Wer C++ lernt, lernt automatisch C mit. Schließlich ist erstere eine Spracherweiterung von letzterer.



  • ~~fricky schrieb:

    Eigentlich gar nie, denn new normal muss man kein delete zum new dazu schreiben, da das ungefähr so aussieht:

    if (blablubb) {
        boost::scoped_ptr< my_class >( new my_class );
    }
    

    ^^ warum so eine abgefahrene zeile hinschreiben mit zwei mal 'my_class' darin? kannste nicht 'new' überladen, so dass es sich wie ein 'scoped-new' verhält?

    asc schrieb:

    Wenn C++ ach soooo schlecht ist, sagt mir mal warum es sich wie C noch immer hält?

    es gibt viel suboptimales und veraltetes zeug, das sich hält und hält. es reicht meistens aus, dass es gerade so eben funktioniert.
    🙂



  • u_ser-l schrieb:

    Man kann nicht C++ ohne C lernen, es sei denn, man will nur eine Teilsprache von C++ lernen.

    Wer C++ lernt, lernt automatisch C mit. Schließlich ist erstere eine Spracherweiterung von letzterer.

    Ich habe nie C gelernt, bin nur durch einige Chaosprojekte auf C gestossen. Die Aussage das man C++ nicht ohne C lernen kann muss also falsch sein. Die einzigen Bestandteile die ich von C nutze ist der Header cmath (for, while etc. sind auch C++, und nicht nur C).

    Und C++ ist nicht eine Spracherweiterung von letzterer, sondern eine eigenständige Sprache die ihre Wurzeln zwar in C hat, aber nicht C ist. Zudem sind die Sprachparadigmen unterschiedlich. Selbst wenn ich unter C++ prozedural programmiere, programmiere ich dennoch anders als ich es unter C tuen würde (Alleine schon wegen Verwendung anderer Schlüsselwörter und Bibliotheksfunktionen die teilweise auf anderen Ansetzen basieren).

    cu André



  • ~fricky schrieb:

    ^^ warum so eine abgefahrene zeile hinschreiben mit zwei mal 'my_class' darin? kannste nicht 'new' überladen, so dass es sich wie ein 'scoped-new' verhält?

    Weil das Prinzip von C++ weiterhin bleibt, das man es sich aussuchen kann. Zudem wäre es Schwachsinn ein new so zu überladen das es sich wie ein "scoped-new" verhält, wenn man es an anderer Stelle auch mit einem shared_ptr etc. einsetzen will.

    Flexibilität kostet manchmal etwas, die Mehrkosten in dem Fall sind aber wirklich nur für Schreibfaule relevant.

    ~fricky schrieb:

    es gibt viel suboptimales und veraltetes zeug, das sich hält und hält. es reicht meistens aus, dass es gerade so eben funktioniert.
    🙂

    <ironie>Stimmt, genau darum werden auch neue Projekte noch in C++ (und auch C) begonnen.</ironie>



  • asc schrieb:

    [
    Ich habe nie C gelernt, bin nur durch einige Chaosprojekte auf C gestossen.

    soso, C code ist also per default chaotische, ne? dabei hab' ich gestern erst irgendwo gelesen, dass sich der C++ user nicht für die C-wurzeln seiner lieblingssprache schämen sollte.
    🙂



  • audacia schrieb:

    Dafür aber manuelles Speichermanagement. Natürlich kann man sich das mit Smart-Pointern o.ä. vereinfachen - aber das ist auch wieder eine GC-Variante.

    wenn raii bei dir unter gc fällt...
    dann hat c++ ja einen gc und der artikel ist immernoch falsch.

    Oder falls du __closure in C++Builder meinst: das ist eine retrospektiv als unglücklich einzuschätzende Wortwahl, hat aber mit den anonymen Methoden von Delphi 2009, besser bekannt als Closures, nicht das Geringste zu tun.

    nein, ich meine die closures aus dem neuen c++ standard

    Was auch immer. Das komplette "Jedes struct ist jetzt eine Klasse" inklusive aller Implikationen, eine davon z.B. Default-, Kopierkonstruktor und Zuweisungsoperator für alle Klassen, ist ein gewaltiger Designfehler - IMHO.

    begründung?
    weil value semantik schlecht ist?

    Shade Of Mine schrieb:

    der artikel ist doof

    Du bist unqualifiziert.

    value semantik ist schlecht - und dennoch sagt der artikel dass einige sachen ohne value semantik ja garnicht schön möglich sind.

    du kannst referenz semantik mit hilfe von value semantik total easy simulieren. du kannst aber mit referenz semantik keine value semantik simulieren.

    ergo ist value semantik essentiell.
    schau dir java an: du tust dauernd clone aufrufen und was ist das erste was man einem java programmierer beibringt? finger weg von clone. weils ein käse ist.

    ja, reine referenz semantik ist wahnsinnig toll.

    Shade Of Mine schrieb:

    das ist eine zusatz information die delete nicht braucht -> du sparst performance

    Abstrus.

    Der tatsächliche Grund dürfte sein, daß new[] erst nach new eingeführt wurde und man vermutlich irgendein ABI nicht kaputtmachen wollte.

    was hat source code mit ABI zu tun?

    und du kannst new effizienter implementieren als new[] - ist einfach so.
    ob das jetzt relevant ist oder nicht sei mal dahin gestellt, aber der vc++ hat früher zB ein new als new[1] implementiert und ist später davon weggegangen.



  • asc schrieb:

    Ich habe nie C gelernt,

    doch, hast Du. Und zwar implizit durch Mitlernen im Rahmen von C++

    Wenn man von C++ alles herausnimmt, was von C stammt, kann man nicht einmal

    int main(){; }
    

    schreiben, denn sowohl int als auch die Funktionsschreibweise mit (){...} und Semikolon stammen von C.

    Nur weil man in "reinem" C++ (was immer das auch sein mag) die stdlib nicht benutzt und Zeiger durch Referenzen ersetzt (und noch ein paar andere C-Spezialitäten vermeidet, wenn möglich), heißt das doch nicht, daß man damit kein C mehr benutzt.

    asc schrieb:

    Und C++ ist nicht eine Spracherweiterung von letzterer,

    Doch, und zwar von C90. Ist doch nichts Schlimmes daran, oder ? C ist ja auch ein portabler Assembler, na und ? Beides (C++ als OO-Spracherweiterung von C, und C als portabler Assembler) macht C und C++ zu unverzichtbaren Werkzeugen mit Alleinstellungsmerkmalen. Gut so.

    Grüße



  • Shade Of Mine schrieb:

    wenn raii bei dir unter gc fällt...
    dann hat c++ ja einen gc und der artikel ist immernoch falsch.

    Nö. Er sagt ja nicht, daß es unmöglich wäre. Aber um effizient Daten an Closures weiterzugeben, muß man Smart-Pointer (oder natürlich den neuesten Versuch, den ursprünglichen Designfehler erträglicher zu machen, nämlich die Move-Semantik) bemühen, also einen mehr oder weniger manuellen GC-Mechanismus. In einer Umgebung mit GC gehts einfach so.

    Shade Of Mine schrieb:

    Was auch immer. Das komplette "Jedes struct ist jetzt eine Klasse" inklusive aller Implikationen, eine davon z.B. Default-, Kopierkonstruktor und Zuweisungsoperator für alle Klassen, ist ein gewaltiger Designfehler - IMHO.

    begründung?
    weil value semantik schlecht ist?

    Barry Kelly schrieb:

    Thing is, writing correct value types is far harder than writing correct Java-style types, and C++ has some features that seem to make value types the default.
    ...
    But when did common domain objects like Person, Car and Account ever need to act like integers, freely copyable and duplicated hither and thither?

    Shade Of Mine schrieb:

    ergo ist value semantik essentiell.
    schau dir java an: du tust dauernd clone aufrufen und was ist das erste was man einem java programmierer beibringt? finger weg von clone. weils ein käse ist.

    ja, reine referenz semantik ist wahnsinnig toll.

    Für die spreche weder ich noch er. Aber eine saubere Trennung wäre einiges wert gewesen.

    Shade Of Mine schrieb:

    was hat source code mit ABI zu tun?

    Um delete so abzuändern, daß es auch Arrays freigeben müßte, hätte die Metainformation, die new vor dem Speicherblock unterbringt, erweitert werden müssen => ABI-Inkompatibilität. Beim Linken älterer Module kann das relevant sein. (Allerdings bin ich nicht der Auffassung, daß das ein Hinderungsgrund hätte sein müssen.)

    Shade Of Mine schrieb:

    und du kannst new effizienter implementieren als new[] - ist einfach so.

    Ist ja okay - dagegen hat ja niemand etwas. Aber was spricht gegen das hier:

    template <typename T>
        void pseudoHighLevelDelete (T* data)
    {
        if (!data)
            return;
        if (((unsigned*) data)[-1] == 0) // etwa drei ASM-Instruktionen mehr
            data->~T ();
        else
            for (unsigned i = ((unsigned*) data)[-1]; i > 0; --i)
                (data++)->~T ();
        std::free (data);
    }
    

    ?

    asc schrieb:

    Ich habe nie C gelernt

    Dann wirds ja höchste Zeit.

    Edit, @Shade: Obige Fragen, warum man throw 1; braucht und inwiefern etwas, das so unausgegoren ist wie std::type_info, nicht unter deine Auffassung von "undurchdacht" fällt, wären auch noch offen. Und bis jetzt habe ich auch noch kein gutes Argument gehört, warum std::type_info::name() nicht einfach aufgeteilt wurde in eine Mangled-Variante (compilerspezifisch, aber maximale Effizienz) und eine standardisierte Demangled-Variante. Und auch, wozu man auf Gleitkommatypen basierende Enumerationen braucht, weiß ich noch nicht.

    Alternativ kannst du mir aber gerne drei Aspekte von C++ nennen, die ich nicht verstanden habe. 🤡



  • audacia schrieb:

    Nö. Er sagt ja nicht, daß es unmöglich wäre. Aber um effizient Daten an Closures weiterzugeben, muß man Smart-Pointer (oder natürlich den neuesten Versuch, den ursprünglichen Designfehler erträglicher zu machen, nämlich die Move-Semantik) bemühen, also einen mehr oder weniger manuellen GC-Mechanismus. In einer Umgebung mit GC gehts einfach so.

    boost lambda kommt zB ohne allokationen aus...

    move semantik kannst du auch jetzt schon mit mojo haben 😉

    warum genau ist value semantik aber ein design fehler?
    bedenke: value semantik kann referenz semantik simulieren - umgekehrt geht es nicht.

    Thing is, writing correct value types is far harder than writing correct Java-style types, and C++ has some features that seem to make value types the default.
    ...
    But when did common domain objects like Person, Car and Account ever need to act like integers, freely copyable and duplicated hither and thither?

    Irrelevant.

    Natürlich gibt es pitfalls bei bei value typen - aber auch referenz typen sind nicht pitfall-los. zB hast du enorm viele java klassen die interne handles hergeben.

    Shade Of Mine schrieb:

    ergo ist value semantik essentiell.
    schau dir java an: du tust dauernd clone aufrufen und was ist das erste was man einem java programmierer beibringt? finger weg von clone. weils ein käse ist.

    ja, reine referenz semantik ist wahnsinnig toll.

    Für die spreche weder ich noch er. Aber eine saubere Trennung wäre einiges wert gewesen.

    Besser geht immer, aber warum ist value semantik schlecht?
    mächtige features sind oft mit pitfalls verbunden...

    deshalb sind sie aber doch nicht schlecht.
    schau dir C# an - dort wird value und reference semantik getrennt - ist auch nicht wirklich perfekt.

    aber es geht auch nicht um perfektion sondern darum ob es funktioniert. und c++ funktioniert.

    Shade Of Mine schrieb:

    Um delete so abzuändern, daß es auch Arrays freigeben müßte, hätte die Metainformation, die new vor dem Speicherblock unterbringt, erweitert werden müssen => ABI-Inkompatibilität. Beim Linken älterer Module kann das relevant sein. (Allerdings bin ich nicht der Auffassung, daß das ein Hinderungsgrund hätte sein müssen.)

    ich finde die trennung nicht störend und es bringt wie du gesagt hast ja auch performance.
    also wo genau ist das problem?

    anders geht immer. aber damit wird kein problem gelöst, denn new/new[] ist kein problem.

    der new operator ruft übrigens den operator new auf - der new operator muss somit _kein_ bookkeeping machen, während der new[] operator sehr wohl eins machen muss.

    da ich die new operatoren aber selber definieren kann, ist es schwer hier zu optimieren ohne 100 sonderfälle zu betrachten.

    das ganze ist zB dann relevant, wenn du fixed size allokationen hast - dann hast du 0 bookkeeping und nur der new[] operator muss bookkeeping machen.



  • audacia schrieb:

    Edit, @Shade: Obige Fragen, warum man throw 1; braucht

    Warum sollte es verboten werden?

    ich mag nunmal auch einen zeiger werfen können (siehe MFC) und das macht manchmal ja auch sinn. und wenn ich zeiger werfen darf, dann wird es plötzlich sehr komisch wenn ich restrikte was für zeiger ich werfen darf.

    ich sehe keinen sinn einer restriktion. welchen vorteil habe ich, wenn ich verbiete zeiger zu werfen?

    das so unausgegoren ist wie std::type_info, nicht unter deine Auffassung von "undurchdacht" fällt, wären auch noch offen.

    weil es so funktioniert wie es gedacht ist.
    es könnte besser sein, aber ja, so ziemlich alles könnte besser sein.

    name() funktioniert: du kannst es verwenden um eine readable form des typs zu bekommen - die genaue form ist ID. wenn deine implementation es schlecht definiert, jo mei.

    Alternativ kannst du mir aber gerne drei Aspekte von C++ nennen, die ich nicht verstanden habe. 🤡

    exceptions, value semantik und new



  • Erst C oder gleich C++ ???

    Back to topic:

    1. Ja, erst C lernen.
    2. Und auch bei C bleiben.


  • troll



  • Shade Of Mine schrieb:

    audacia schrieb:

    Nö. Er sagt ja nicht, daß es unmöglich wäre. Aber um effizient Daten an Closures weiterzugeben, muß man Smart-Pointer (oder natürlich den neuesten Versuch, den ursprünglichen Designfehler erträglicher zu machen, nämlich die Move-Semantik) bemühen, also einen mehr oder weniger manuellen GC-Mechanismus. In einer Umgebung mit GC gehts einfach so.

    boost lambda kommt zB ohne allokationen aus...

    Baut man mit boost lambda etwa Closures? Wie sieht das aus? Wo wird die Umgebung gespeichert?



  • Bashar schrieb:

    Baut man mit boost lambda etwa Closures? Wie sieht das aus? Wo wird die Umgebung gespeichert?

    kann man machen, ja.

    A language implementation cannot easily support full closures if its run-time memory model allocates all local variables on a linear stack. In such languages, a function's local variables are deallocated when the function returns. However, a closure requires that the free variables it references survive the enclosing function's execution. Therefore those variables must be allocated so that they persist until no longer needed. This explains why typically languages that natively support closures also use garbage collection. The alternative is for the language to accept that certain use cases will lead to undefined behaviour, as in the proposal for lambda expressions in C++.



  • topic --> out off topic --> out out off topic ... => in future meinungsverschiedenheiten zwischen programmierer

    greetz!


Anmelden zum Antworten