john 0 erklaert C++ casts



  • @Columbo sagte in Run-Time Check Failure #2:

    Hoer auf so einen Schwachsinn zu faseln. Das ist offensichtlich nicht ausreichend.

    Der Schwachsinn kommt von dir! Genau aus diesem Grund darf man an dieser Stelle reinterpret_cast nicht nutzen, weil es eben fundamentale Fehler überdeckt. Zeiger beliebigen Typs lassen sich mit static_cast konvertieren, wenn das scheitert, dann wird versucht etwas anderes als einen Zeiger zu konvertieren, und dann läuft etwas ganz falsch.



  • Ich benutze C-Style Casts in C++.

    Solange man die Casts richtig schreibt erzeugt das weniger Overhead, ist kürzer im Text und macht was verlangt wird.

    Es ist keine große Mühe einen Cast richtig zu schreiben und man kann das auch einfach verallgemeinern, dann hat man solche Probleme nicht.



  • @eigenartig sagte in Run-Time Check Failure #2:

    Ich benutze C-Style Casts in C++.

    C-Casts überdecken etliche Fehler, die man sofort sieht, wenn man C++-Casts verwendet. Wenn man versucht einen vermeintlichen Pointer in einen anderen Pointer mit static_cast zu casten, und es funktioniert nicht. Dann versucht man etwas anderes als ein Pointer zu casten, und das schlägt aus gutem Grund fehl. C-Casts funktionieren immer wie ein Dampfhammer, der Cast funktioniert, aber man erzeugt ganz schnell UB.

    reinterpret_cast im Kontext von Zeiger braucht man nur dann, wenn man ein Zahl (z.B. konstante Speicheradresse) in einen Zeiger zu konvertieren.



  • @eigenartig

    Solange man die Casts richtig schreibt erzeugt das weniger Overhead,

    Welchen Overhead?



  • gcc lässt keinen static_cast zwischen beliebigen Zeigertypen zu, und soweit ich weiß auch aus gutem Grund, aber diskutiert hier ruhig weiter. Bin auf das Argument gespannt, warum das eigentlich erlaubt sein sollte.



  • @john-0 sagte in Run-Time Check Failure #2:

    C-Casts funktionieren immer wie ein Dampfhammer, der Cast funktioniert, aber man erzeugt ganz schnell UB.

    Sollen sie auch. Ich finde es fragwürdig einen Cast falsch zu schreiben.

    @manni66 sagte in Run-Time Check Failure #2:

    Welchen Overhead?

    Außer bei dynamic_cast<> wohl keinen.


  • Mod

    Wurde mir zu bloed, diesen Unsinn im OT zu ertragen. Uns kann @john-0 hier gerne erklaeren, ob

    struct T {}; 
    char* p;
    static_cast<T*>(p); 
    

    wohlgeformt ist, nachdem er es fuer notwendig befand, in fettgedrucktem Text zu widersprechen (spoiler: nicht einmal VC++ ist so bescheuert, das zu uebersetzen).

    Strapaziere nicht den Geduldsfaden.



  • @Columbo sagte in john 0 erklaert C++ casts:

    Wurde mir zu bloed, diesen Unsinn im OT zu ertragen.

    Du missbrauchst deine Rolle als Mod massiv. Namen von Nutzern als Threadtitel zu wählen ist niveaulos, und dazu schreibst du zu den technischen Belangen gröbsten Unfug (siehe ursprünglicher Thread was mit reinterpret_cast alles falsch gehen kann).

    Uns kann @john-0 hier gerne erklaeren, ob

    struct T {}; 
    char* p;
    static_cast<T*>(p); 
    

    Das geht problemlos via

    struct T{};
    
    char*p;
    void* pv = static_cast<void*>(p);
    T* pT = static_cast<T*>(pv);
    

    Ok, ich habe den zweiten Casts vergessen, aber es ist kein fundamental Fehler.



  • void* ist also sicherer als reinterpret_cast - ja dann ...



  • Wenn reinterpret_cast benutzt wird, um einen Zeiger auf T in einen Zeiger auf U zu konvertieren, ist das per Definition dasselbe wie den Zeiger auf T zuerst mithilfe von static_cast in einen Zeiger auf void, und das Ergebnis dann mit static_cast in einen Zeiger auf U zu konvertieren.

    Bin aber immer noch gespannt, wer hier jetzt genau Schwachsinn erzählt hat 🙂



  • @Bashar sagte in john 0 erklaert C++ casts:

    Wenn reinterpret_cast benutzt wird, um einen Zeiger auf T in einen Zeiger auf U zu konvertieren, ist das per Definition dasselbe wie den Zeiger auf T zuerst mithilfe von static_cast in einen Zeiger auf void, und das Ergebnis dann mit static_cast in einen Zeiger auf U zu konvertieren.

    Das Problem bei reinterpret_cast ist, dass man da mit nicht nur die Zeiger konvertieren kann, sondern

    #include <cstdlib>
    
    struct Foo{};
    
    int main () {
        size_t s = 1;
        Foo* pF = reinterpret_cast<Foo*>(s);  // 1
        Foo* p  = reinterpret_cast<Foo*>(&s); // 2
    }
    

    auch das hier. Wenn Du den Unterschied zwischen Zeile 1 und 2 verstanden hast, dann können wir weiter diskutieren.



  • @john-0 sagte in john 0 erklaert C++ casts:

    @Bashar sagte in john 0 erklaert C++ casts:

    Wenn reinterpret_cast benutzt wird, um einen Zeiger auf T in einen Zeiger auf U zu konvertieren, ist das per Definition dasselbe wie den Zeiger auf T zuerst mithilfe von static_cast in einen Zeiger auf void, und das Ergebnis dann mit static_cast in einen Zeiger auf U zu konvertieren.

    Das Problem bei reinterpret_cast ist, dass man da mit nicht nur die Zeiger konvertieren kann, sondern

    #include <cstdlib>
    
    struct Foo{};
    
    int main () {
        size_t s = 1;
        Foo* pF = reinterpret_cast<Foo*>(s);  // 1
        Foo* p  = reinterpret_cast<Foo*>(&s); // 2
    }
    

    auch das hier. Wenn Du den Unterschied zwischen Zeile 1 und 2 verstanden hast, dann können wir weiter diskutieren.

    das geht aber doch mit dem C-Style-Cast genauso ( Zeile 1 ist gemeint ) ....



  • @It0101 sagte in john 0 erklaert C++ casts:

    das geht aber doch mit dem C-Style-Cast genauso ( Zeile 1 ist gemeint ) ....

    Ja, und deshalb sollte man weder C-Style-Casts noch reinterpret_cats verwenden, wenn dies nicht unbedingt notwendig ist. Du musst nur ein "&" oder "*" vergessen und schon hast Du UB ins Programm eingebaut und der Compiler wirft keinerlei Warnung aus.



  • @john-0 sagte in john 0 erklaert C++ casts:

    Das geht problemlos via

    struct T{};
    
    char*p;
    void* pv = static_cast<void*>(p);
    T* pT = static_cast<T*>(pv);
    

    Das kompiliert zwar, aber es ist trotzdem fürchterlich.



  • @john-0 sagte in john 0 erklaert C++ casts:

    @It0101 sagte in john 0 erklaert C++ casts:

    das geht aber doch mit dem C-Style-Cast genauso ( Zeile 1 ist gemeint ) ....

    Ja, und deshalb sollte man weder C-Style-Casts noch reinterpret_cats verwenden, wenn dies nicht unbedingt notwendig ist. Du musst nur ein "&" oder "*" vergessen und schon hast Du UB ins Programm eingebaut und der Compiler wirft keinerlei Warnung aus.

    Da stimme ich dir zu. C-Style-Casts und auch reinterpret sollten absolute Ausnahmen sein. Ich brauche die Schlampen-Casts ( so fasse ich die zusammen ) eigentlich fast nie. Eigentlich caste ich überhaupt relativ selten. Ist auch heutzutage selten notwendig, wenn man sauber mit Templates und Vererbung arbeitet.

    Ich benutze diese Casts eigentlich nur hardware-nah bei der Speicherbesorgung und eben bei Puffern, wenn man z.B. den Typ kennt, der als nächstes im Puffer folgt, dann caste ich auch mal von char* nach T*.



  • @It0101 sagte in john 0 erklaert C++ casts:

    Das kompiliert zwar, aber es ist trotzdem fürchterlich.

    Es ist eine Folge des gewählten Designs.



  • Ich habe eigentlich nicht verstanden warum ihr euch hier so in die Haare bekommt.
    Dass C-Style und reinterpret_cast zu vermeiden sind, ist doch eigentlich Konsens.



  • C-Style Casts sind viel übersichtlicher und nicht in langnamigen Funktionen versteckt. Ausnahmen für mich sind hier std::move() weil der Name vergleichsweise besser aussieht.

    So schlimm kann das schon nicht sein das richtig zu machen.



  • @eigenartig sagte in john 0 erklaert C++ casts:

    C-Style Casts sind viel übersichtlicher und nicht in langnamigen Funktionen versteckt

    Hast du kein Intellisense / Autovervollständigen?
    Für die meisten Befehle muss ich gerade mal vier Buchstaben eingeben.

    Also das schlampige Arbeiten mit "ich will nicht soviel tippen" zu begründen, ist in der heutigen Zeit schon bedenklich 😉 Nichts für ungut.



  • @It0101 sagte in john 0 erklaert C++ casts:

    Also das schlampige Arbeiten mit "ich will nicht soviel tippen" zu begründen, ist in der heutigen Zeit schon bedenklich Nichts für ungut.

    Das stimmt doch gar nicht. Es ist einfach viel hübscher nur (T) zu verwenden.



  • @It0101 sagte in john 0 erklaert C++ casts:

    Ich habe eigentlich nicht verstanden warum ihr euch hier so in die Haare bekommt.

    Der Herr reagiert sehr dünnhäutig darauf, wenn man seinen Stil zu programmieren kritisiert. Einige hier im Forum hängen einer Ideologie an, dass man keinerlei manuelle Speicherverwaltung machen dürfe. Das führt dann in diesem konkreten Beispiel zu einem zweifelhaften Design. Wann wenn nicht in einem Container sollte man manuelle Speicherverwaltung machen?

    P.S. Wie man es ohne cast hinbekommt, habe ich im original Thread mittlerweile gepostet. Das ist die Minimallösung. Die saubere Lösung wäre die Containerklasse komplett mit eigener Speicherverwaltung zu schreiben, und dann wird auch schnell ersichtlich, weshalb propagate_on_container_swap, propagate_on_container_copy_assigment, propagate_on_container_move_assigment alles andere als Trivialitäten sind.


Log in to reply