Sprachmittel, die ihr nie benutzt



  • Aus Interesse wollte ich euch mal fragen, welche Sprachmittel ihr (praktisch) nie verwendet. Wichtig ist, dass ich mich hier nur auf C++98 und nicht auf Bibliotheksmittel beziehe. Gesamthaft existieren natürlich etliche Regeln im C++-Standard, von denen man kaum Gebrauch macht. Im Vordergrund sollen einigermassen bekannte und bewusst als Feature aufgefasste Möglichkeiten stehen.

    Sprachmittel, die ich nie einsetze:

    • Exception-Spezifikationen
    • variable Argumentlisten
    • Speicherklassen-Schlüsselwörter register und auto
    • protected -Vererbung
    • Pointer-to-Member (nicht Memberfunktionszeiger)
    • Function-Style- und C-Casts
    • Bitfelder
    • Digraphen, Trigraphen, alternative Schlüsselwörter ( and etc.)
    • export

    Sehr selten:

    • virtuelle Vererbung
    • eigene new - und delete -Operatoren
    • Funktionstemplate-Spezialisierung
    • const_cast , dynamic_cast
    • union
    • goto
    • volatile
    • Arrays

    Gibt sicher noch mehr, die Listen kann ich ja noch ergänzen... Wie siehts bei euch aus?



  • []variable Argumentlisten
    [
    ]Speicherklassen-Schlüsselwörter register und auto
    [] protected -Vererbung
    [
    ]Pointer-to-Member (nicht Memberfunktionszeiger)
    []Function-Style- und C-Casts <-- wegen grep
    [
    ]Bitfelder
    []Digraphen, Trigraphen, alternative Schlüsselwörter ( and etc.)
    [
    ] export [/list]Sehr selten:

    • virtuelle Vererbung
    • eigene new - und delete -Operatoren
    • union
    • goto
    • volatile
    • Arrays

    Gibt sicher noch mehr, die Listen kann ich ja noch ergänzen...
    []vector<bool> <--- fiese bugs die jede menge zeit kosten
    [
    ]inline <--- mittlerweile sind compiler schlau genug es selber zu optimieren
    []unsigned statt unsgined int wg. auto int
    [
    ]Rückgabe von Roh Zeigern *
    [*]Eigenes delete, dafür gibt es shared_ptr, unique_ptr

    Um const_cast , dynamic_cast kommt man leider nicht rum wenn man doppelten code in operatoren vermeiden möchte.



  • Bei mir wäre die Liste ein wenig länger - aber das könnte auch daran liegen, daß ich im täglichen Einsatz nichts mit C++ zu tun habe 😃

    Aber ansonsten fallen mir als kaum bis gar nicht genutzte Features noch Funktionszeiger, #define (außer für Include-Guards) und globale Variablen ein (letztere aus Prinzip und wegen der dadurch möglichen Nebeneffekte).



  • asdsad schrieb:

    vector<bool> <--- fiese bugs die jede menge zeit kosten

    Ist ein Bibliotheks- und kein Sprachmittel.

    asdsad schrieb:

    inline <--- mittlerweile sind compiler schlau genug es selber zu optimieren

    Brauche ich nicht zur Optimierung, aber um Funktionen im Header definieren zu können (für Header-Only-Funktionalität)

    asdsad schrieb:

    Rückgabe von Roh Zeigern *

    Brauche ich schon ab und zu. Ich sehe auch nichts, was dagegen spricht, wenn der Zeiger keinen Besitz überträgt.

    asdsad schrieb:

    Eigenes delete, dafür gibt es shared_ptr, unique_ptr

    Ja, delete benutze ich im Anwendungscode auch recht wenig, delete[] noch viel weniger. Aber ich habe in letzter Zeit einige Low-Level-Dinge wie Smart-Pointer implementiert.

    asdsad schrieb:

    Um const_cast , dynamic_cast kommt man leider nicht rum wenn man doppelten code in operatoren vermeiden möchte.

    dynamic_cast brauchst du dazu nicht. Und bei mir sind solche Operatoren wohl meist trivial genug gewesen, um Code zu duplizieren...



  • Wenn ich pur C++ programmiere, dann verwende ich selten...

    - char* btw. char[] (stattdessen die string-Klasse)
    - defines
    - structs
    - protected Vererbung

    Da fallen mir noch ein dutzend mehr Dinge ein. 🙂



  • CStoll schrieb:

    Funktionszeiger

    Brauche ich oft – meist um sie gleich in eine std::function zu stecken, aber von Zeit zu Zeit werden sie auch direkt abgespeichert.

    CStoll schrieb:

    #define (außer für Include-Guards)

    Habe ich auch ab und zu. Nicht nur für Konfiguration und bedingte Kompilierung, sondern auch, um Boilerplate-Code wie Traits-Spezialisierungen anwenderfreundlich zu machen.

    CStoll schrieb:

    globale Variablen ein (letztere aus Prinzip und wegen der dadurch möglichen Nebeneffekte).

    Konstanten habe ich manchmal, vor allem in .cpp-Dateien. Ich weiss nicht, ob du zu den Leuten gehörst, für die Konstanten keine Variablen sind 😉

    satanfreze schrieb:

    - char* btw. char[]

    Benutze ich für Stringliterale.

    satanfreze schrieb:

    - structs

    Habe ich andauernd für Funktoren und kleine Hilfsklassen.



  • Nexus schrieb:

    Brauche ich schon ab und zu. Ich sehe auch nichts, was dagegen spricht, wenn der Zeiger keinen Besitz überträgt.

    const Objekt const * GetConstMember() const;
    ...
    Objekt * tmp = const_cast<Objekt *>(GetConstMember());
    delete tmp; // Futsch ist der const Member
    

    dynamic_cast <-- ist irgendwie dazwischengerutscht

    Nexus schrieb:

    Und bei mir sind solche Operatoren wohl meist trivial genug gewesen, um Code zu duplizieren...

    Wenn man einen [] hat der einmal ein eine const memberfunktion und einmal zuordnung ist muss man zwangsläufig duplizieren oder const_casten.



  • Nexus schrieb:

    CStoll schrieb:

    globale Variablen ein (letztere aus Prinzip und wegen der dadurch möglichen Nebeneffekte).

    Konstanten habe ich manchmal, vor allem in .cpp-Dateien. Ich weiss nicht, ob du zu den Leuten gehörst, für die Konstanten keine Variablen sind 😉

    globale Konstanten halte ich für unproblematisch, Variablen (in dem Sinn, daß sich ihr Wert ändern kann) führen schnell zu Spagetti-Code und endlosen Debugging-Sitzungen, weil du nicht einschränken kannst, wo sie tatsächlich genutzt und verändert werden (häufig an einer Stelle, die mit dem eigentlichen Problem gar nichts zu tun haben sollte).



  • asdsad schrieb:

    Objekt * tmp = const_cast<Objekt *>(GetConstMember());
    delete tmp; // Futsch ist der const Member
    

    Wer ohne zu denken delete auf Zeiger anwendet, nimmt die Probleme geradezu in Kauf. Als Bibliotheksentwickler kann man doch nicht auf solche Leute Rücksicht nehmen. Übrigens brauchst du dafür nicht mal const_cast .

    asdsad schrieb:

    Wenn man einen [] hat der einmal ein eine const memberfunktion und einmal zuordnung ist muss man zwangsläufig duplizieren oder const_casten.

    Lustig, jetzt habe ich tatsächlich gerade eine Codestelle entdeckt, wo ich etwa 5 Zeilen Code dupliziere, allerdings kein Operator. Könnte ich mir echt const_cast überlegen 🙂

    CStoll schrieb:

    globale [...] Variablen [...] führen schnell zu Spagetti-Code und endlosen Debugging-Sitzungen

    Völlig einverstanden 😉



  • Nexus schrieb:

    • Exception-Spezifikationen Ebenfalls nicht.
    • variable Argumentlisten Nur für Meta-Programming.
    • Speicherklassen-Schlüsselwörter register und auto Ebenfalls nicht.
    • protected -Vererbung Ebenfalls nicht.
    • Pointer-to-Member (nicht Memberfunktionszeiger) Ebenfalls nicht.
    • Function-Style- und C-Casts Ebenfalls nicht.
    • Bitfelder Extrem selten. Wenn ich mal bools packen möchte und Namen dazu haben will.
    • Digraphen, Trigraphen, alternative Schlüsselwörter ( and etc.) Ebenfalls nicht.
    • export Ebenfalls nicht.

    Sehr selten:

    • virtuelle Vererbung Gar nicht.
    • eigene new - und delete -Operatoren Ebenfalls selten.
    • Funktionstemplate-Spezialisierung Das sagt mir jetzt nichts. Vermutlich erkenne ich's soofort, wenn ich's sehe.
    • const_cast , dynamic_cast const_cast noch nie, danymic_cast sehr selten.
    • union Gelegentlich.
    • goto Nie.
    • volatile Annähernd nie.
    • Arrays Für const char [], die zur Compilezeit bekannt sind. Ansonsten nicht.*


  • Wurde die Symmetrie des eingebauten Indexing Operators schon genannt?

    Also dass pointer[index] einfach zu *(pointer+index) wird, und man es daher auch als index[pointer] schreiben kann?

    Das ist nämlich auch was was ich nie verwende.



  • Interessanter wird es doch bei der Frage: Auf was könntet ihr verzichten? Also bei mir wären da nur Trigraphen, register, auto. Wobei auto von C++11 wohl eh eine neue Bedeutung bekommt.



  • hustbaer schrieb:

    Wurde die Symmetrie des eingebauten Indexing Operators schon genannt?

    Es ist eher die Symmetrie des eingebauten Plus-Operators.



  • Sprachmittel, die ich nie einsetze:

    • Exception-Spezifikationen
    • variable Argumentlisten
    • Speicherklassen-Schlüsselwörter register und auto
    • protected -Vererbung
    • Pointer-to-Member (nicht Memberfunktionszeiger)
    • Bitfelder
    • Digraphen, Trigraphen, alternative Schlüsselwörter ( and etc.)
    • export
    • eigene new - und delete -Operatoren
    • union
    • goto
    • volatile
    • Arrays
    • C-String

    Sprachmittel, die ich selten einsetze:

    • Globale Variablen (und wenn auch nur für Objekt-Registrierung an anderen Klassen, oder Konstanten).
    • #define (Nur für Headerguards und bedingte Compilierung, niemals für Konstanten und Funktionsersatz)
    • delete (In der Regel ziehe ich Smartpointer wie scoped_ptr/unique_ptr & Co vor).


  • volkard schrieb:

    hustbaer schrieb:

    Wurde die Symmetrie des eingebauten Indexing Operators schon genannt?

    Es ist eher die Symmetrie des eingebauten Plus-Operators.

    Hihi, OK.
    Dann eben dass der Indexing-Operator auf *(a+b) abgebildet wird.
    Und Symmetrie ist sicher auch der falsche Ausdruck, aber ich glaube ihr versteht was ich meine.



  • hustbaer schrieb:

    volkard schrieb:

    hustbaer schrieb:

    Wurde die Symmetrie des eingebauten Indexing Operators schon genannt?

    Es ist eher die Symmetrie des eingebauten Plus-Operators.

    Hihi, OK.
    Dann eben dass der Indexing-Operator auf *(a+b) abgebildet wird.

    Das ist soweit eigentlich OK, es ist wirklich die Kommutativität von +, die nicht immer sinnvoll ist.



  • Bashar schrieb:

    Das ist soweit eigentlich OK, es ist wirklich die Kommutativität von +, die nicht immer sinnvoll ist.

    Wo sonst? Und findest du die Nicht-Kommutativität bei std::string sinnvoll?



  • Nexus schrieb:

    Bashar schrieb:

    Das ist soweit eigentlich OK, es ist wirklich die Kommutativität von +, die nicht immer sinnvoll ist.

    Wo sonst? Und findest du die Nicht-Kommutativität bei std::string sinnvoll?

    Da war die Wahl de Zeichens '+' eine unglückliche Wahl.



  • Nexus schrieb:

    Bashar schrieb:

    Das ist soweit eigentlich OK, es ist wirklich die Kommutativität von +, die nicht immer sinnvoll ist.

    Wo sonst? Und findest du die Nicht-Kommutativität bei std::string sinnvoll?

    Ja klar, warum nicht?



  • volkard schrieb:

    Nexus schrieb:

    Wo sonst? Und findest du die Nicht-Kommutativität bei std::string sinnvoll?

    Da war die Wahl de Zeichens '+' eine unglückliche Wahl.

    Das ist Geschmackssache, ich finde es jedenfalls durchaus intuitiv bei der Anwendung.


Anmelden zum Antworten