Speicherreservierung mit new



  • padreigh schrieb:

    Nein.

    #define NULL meins
    

    Ob das erlaubt ist?
    Aber mach doch

    #define new new(badHint)
    

  • Mod

    Thou shalt not redefine reserved identifiers!

    NULL, new, private, usw. zählen alle dazu.

    padreigh schrieb:

    Mist 😉 gibts irgendwo eingentlich eine Liste von UB? Wo schau ich sowas nach?

    Den Standard nach "undefined" durchsuchen? Das lohnt aber den Aufwand nicht, gesunder Menschenverstand und Erfahrung sollten für die meisten Fälle reichen und ansonsten guckt man eben gezielt im Standard. Hier Kapitel 2.10 "Identifiers" wo man schon private und new findet und von dort wird man weiterverwiesen nach 17.4.3.1 "Reserved names" wo dann indirekt NULL ausgeschlossen wird.



  • padreigh schrieb:

    Mist 😉 gibts irgendwo eingentlich eine Liste von UB? Wo schau ich sowas nach?

    Im C++ Standard...



  • Ich komm zwar in dem pdf das ich fand (Dank für den Link) (N3225 10-0215 Working Draft, Standard for Programming Language C++ Pete Becker 2010-11-27 2010-11 N3126=10-0116=) leicht andere Kapitelnummern aber sieht so aus als wär das tatsächlich verboten. Snüff. Wie bekomm ich denn heraus welche Doku "meinem" C++ entspricht? (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5))



  • padreigh schrieb:

    Wie bekomm ich denn heraus welche Doku "meinem" C++ entspricht? (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5))

    Der Sinn eines Standards ist ja gerade, dass es nicht verschiedene Versionen gibt 😉

    Die meisten Compiler haben zwar gewisse Erweiterungen, aber um portabel programmieren zu können, solltest du dich soweit möglich an den C++-Standard halten. Abweichungen findest du in der Dokumentation deines Compilers.



  • padreigh schrieb:

    Wie bekomm ich denn heraus welche Doku "meinem" C++ entspricht? (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5))

    Das ist der C++ Standard (und eben das aktuelle Working Draft für den Neuen und nicht der momentan gültige Standard, darum die etwas anderen Nummern) und keine Doku...



  • Hab ich die Frage falsch verstanden? Hier steht doch ganz klar, dass die Rückgabe von new NULL ist, wenn kein Speicher mehr vorhanden ist und die nothrow-Variante vom Operator new genommen wird:

    http://www.cplusplus.com/reference/std/new/operator%20new/



  • VielleichtFalschversteher schrieb:

    Hab ich die Frage falsch verstanden? Hier steht doch ganz klar, dass die Rückgabe von new NULL ist, wenn kein Speicher mehr vorhanden ist und die nothrow-Variante vom Operator new genommen wird:

    http://www.cplusplus.com/reference/std/new/operator%20new/

    Von nowthrow war hier nie die Rede, es geht um das Verhalten von new. Und da garantiert der Standard, dass man den Speicher bekommt oder eine bad_alloc exception geworfen wird.



  • DocShoe schrieb:

    Von nowthrow war hier nie die Rede, es geht um das Verhalten von new. Und da garantiert der Standard, dass man den Speicher bekommt oder eine bad_alloc exception geworfen wird.

    Es war die Rede vom operator new und der beinhaltet unter anderem die nothrow-Variante. Deswegen kann man doch nicht allgemein sagen, dass der Pointer, der mit new initialisiert wird, niemals NULL ist.



  • Nein, die Frage war

    Garantiert mir der C++-Standard, dass ein Zeiger der auf ein mit new reserviertes Objekt [zeigt] immer ungleich NULL ist?

    Die Reservierung ist aber nicht erfolgt, wenn new wirft.



  • Eisflamme schrieb:

    Die Reservierung ist aber nicht erfolgt, wenn new wirft.

    Genau! Wenn geworfen wird, will ich überhaupt nicht auf Gleichheit mit NULL prüfen.

    Danke!


  • Mod

    EOutOfResources schrieb:

    Hallo

    Garantiert mir der C++-Standard, dass ein Zeiger der auf ein mit new reserviertes Objekt immer ungleich NULL ist?

    MfG, EOutOfResources

    NULL ist nach Konvertierung in einen beliebigen Zeigertyp ein Nullzeiger. Ein Nullzeiger zeigt definitionsgemäß niemals auf irgendein Objekt (ob nun per new oder irgendwie anders erzeugt).
    Im Umkehrschluss folgt, dass wenn new erfolgreich war und ein Objekt erzeugt hat, das Resultat kein Nullzeiger sein kann.



  • Long story short: new wirft eine std::bad_alloc exception wenn das allokieren fehlschlägt. Außer es handelt sich um die nothrow Variante oder es kommt sonstwie ein komisch überladener operator new() ins Spiel. Wenn new wirft brauchst du nichts auf 0 zu prüfen denn soweit kommst du dann sowieso gar nicht...



  • c++ Standard hin oder her, was ist eigentlich mit denen, die ihren Code mit deaktivierten Exceptions bauen müssen - das kenne ich von einigen Projekten für eingebettete Systeme, das erste, was ausgeschaltet wird, ist Exception-Handling. Was macht new in diesem Fall, was garantiert der Standard 😕



  • 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.


Anmelden zum Antworten