Speicherreservierung mit new



  • abc.w schrieb:

    Was macht new in diesem Fall, was garantiert der Standard 😕

    gar nix, "Exception Handling ausschalten" ist im Standard nicht vorgesehen...



  • Na, seht ihr, also doch alle Zeiger schön und brav mit NULL vergleichen 🙂



  • abc.w schrieb:

    Na, seht ihr, also doch alle Zeiger schön und brav mit NULL vergleichen 🙂

    Öhm nein, in Standard C++ mal in der Regel nicht, da wirft new eine exception!?



  • Na, damit das System nicht abstürzt, damit man darauf reagieren kann, dass plötzlich der Speicher ausgegangen ist, dass etwas total schief läuft 🙂



  • Dafür verwendet man in der Regel exception handling...



  • Nexus schrieb:

    padreigh schrieb:

    Deswegen: 0 statt NULL .

    Man muss immer Pimpl einsetzen und die Body-Klasse in der .cpp-Datei verstecken. Sonst könnte jemand #define private public schreiben und die Kapselung aufheben.

    Ganz klares jain 🙂

    Wenn man die Klasse wirklich "verstecken" will muss man PIMPLn (oder mit Factories arbeiten). Zumindest dann wenn "verstecken" bedeutet dass der Programmierer nichtmal sehen soll welche Member so für die Implementierung verwendet werden. Dazu reicht es nämlich das Header-File zu lesen, ganze ohne böse #define Tricks.

    Wenn es allerdings um Kapselung geht, dann sollte man private in C++ IMO als ausreichen ansehen (*).
    Grund: wenn man eine Klasse im selben Programm (in unterschiedlichen Translation Units) einmal mit public=public und einmal mit public=private übersetzt, dann ist das laut Standard IIRC "undefined behaviour (no diagnostic required)". Und sobald man anfängt sich auf Tricks zu verlassen die offiziell UB sind, kann man viel machen. Debugger anwerfen, nachsehen wie das worauf der PIMPL-Zeiger zeigt so aussieht, eigene Helper-Structs definieren, reinterpret_cast, fertig.

    Ich finde das erwähnenswert, da PIMPL viele Nachteile hat, die man nicht nur deswegen in Kauf nehmen sollte, weil man (fälschlicherweise) denkt damit die Kapselung zu verbessern. Programmieren ist schon genug Arbeit ohne dass man sich das Leben noch unnötigerweise schwer macht 😉

    ----

    *: zumindest so lange eine Klasse keine Memberfunction-Templates hat die public oder protected sind. Der einzig mir bekannte standardkonforme Trick um "private" auszuhebeln ist nämlich der, eine Member-Funktion auf einen im eigenen Programm definierten Typ zu spezialisieren.

    Ich persönlich meide PIMPL allerdings selbst dann WENN die Klasse public Memberfunction-Templates hat, weil es IMO einfach den Aufwand nicht wert ist. Wenn ein Programmierer rumpfuschen will, dann wird er es so oder so machen. private sagt ganz klar "Finger weg", und man muss mehr oder weniger fragwürdige Workarounds anwenden um es auszuhebeln. Das ist gut, denn es vermeidet "Unfälle" bzw. Unklarheiten. Alles was darüber hinaus geht, ist IMO in 95% der Fälle unnötig/übertrieben.



  • abc.w schrieb:

    Na, damit das System nicht abstürzt, damit man darauf reagieren kann, dass plötzlich der Speicher ausgegangen ist, dass etwas total schief läuft 🙂

    new wird niemals 0 zurückgeben, es sei denn man
    * verwendet eine nicht konforme Implementierung oder
    * redefiniert oder überschreibt new selbst oder
    * ruft placement new mit std::nothrow_t auf

    Ein Check gegen 0 ist also weder nötig noch ausreichend, da wie schon geschrieben wurde eine Exception ( std::bad_alloc ) fliegen wird wenn der Speicher ausgeht.

    Nicht ausreichend, weil diese Exception irgendjemand fangen sollte damit das Programm nicht crasht.

    Und nicht nötig, da das Fliegen der Exception dazu führt dass gar kein Ergebnis zurückgegeben wird. Und wo es kein Ergebnis gibt, kann man auch kein Ergebnis gegen 0 prüfen.



  • In meinem Fall will ich den Zeiger mit NULL vergleichen, weil ich nicht weiss, ob schon allokiert wurde.



  • @EOutOfResources:
    Jo, ich hab ja auch auf den Beitrag von abc.w geantwortet.

    EOutOfResources schrieb:

    In meinem Fall will ich den Zeiger mit NULL vergleichen, weil ich nicht weiss, ob schon allokiert wurde.

    3.7.3.1 Allocation functions schrieb:

    2
    (...)
    If the request succeeds, the value returned shall be a nonnull pointer value (4.10) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to an operator delete.

    Ich denke das rechtfertigt ein klares "ja!" 🙂
    (EDIT: "Ja" auf deine ursprüngliche Frage, also ob es garantiert ist und so. Mal abgesehen davon dass z.B. camper ja schon eine bessere Antwort geteben hat -- was ich gerade eben erst gesehen habe.)



  • Hustbaer, ich stimme dir völlig zu. Ich wollte mit meiner Aussage eine Analogie zur Argumentation "weil man NULL neu definieren kann, muss man 0 benutzen" bringen 🙂

    Ich benutze selbst recht selten Pimpl. Eigentlich nur, wenn man dadurch wirklich grosse Abhängigkeiten einsparen kann und sich die Indirektion lohnt. Ich glaube, so ein klassisches Pimpl-Idiom habe ich schon ewig nicht mehr angewandt, eher mal einzelne Member als Zeiger. Und bei Templates kann man oft sowieso nichts machen...


Anmelden zum Antworten