Gründe gegen globale Variabeln



  • Okay, vielen Dank für die vielen Erläuterungen!

    So habe ich das bis jetzt noch nicht gesehen. Ich selber bin Hobbyprogrammierer und als solcher habe ich weder riesigen Sourcecode mit mehreren hundert Klassen und Funktionen noch ein striktes OOP-Design. Deshalb konnte ich auch nicht wirklich nachvollziehen, welche dramatischen Auswirkungen globale Variabeln haben.

    Bis jetzt habe ich auch eigentlich immer in nur mit einer Übersetzungseinheit und mehreren Headern gearbeitet (momentan brauche ich eigentlich auch nicht mehrere CPP-Dateien). Von da her spielt die Deklaration auch nicht so eine grosse Rolle, z.B. habe ich noch nie wirklich extern benötigt. Auch Multithreading und andere Konzepte wie Singletons benötigte ich bisher nicht. Aber ich kann mir vorstellen, dass ich mich gerade bei grösseren Projekten umstellen muss, auch was globale Variabeln betrifft.

    @ LordJaxom
    Ich habe noch ein Beispiel. Ich programmiere in meiner Freizeit ab und zu kleine Games und in meiner Grafikbibliothek (SFML) gibt es eine Fenster-Klasse, die sozusagen hinter allen Grafikaktionen steht. Das heisst, man lässt sie alles zeichnen und anzeigen, sie regelt sogar Tastatur- und Mauseingaben.
    Meiner Ansicht nach ist eine solche globale Variable gerechtfertigt, da sie fast überall benutzt wird (selbst in Logikfunktionen, z.B. für die Höhe und Breite etc.). Mein Code ist aber auch verhältnismässig klein und überblickbar, daher passiert es mir nicht so schnell, dass ich aus Versehen etwas ändere. Und im Weiteren ist es auch eine Klasse, deren Attribute nur über Funktionsschnittstellen manipuliert werden können.

    In solchen Anwendungsbereichen finde ich globale Variabeln sehr praktisch, aber ich kann nach euren Erklärungen auch gut nachvollziehen, wieso sich das (bei mir langfristig) negativ auswirken könnte.



  • Hi Nexus,

    Dein Programmierstil wird sich irgendwann herausbilden - stehe dazu.



  • Scheppertreiber schrieb:

    Hi Nexus,

    Dein Programmierstil wird sich irgendwann herausbilden - stehe dazu.

    Habe ich denn irgendwo nicht dazu gestanden? Ich erklärte ja mein Niveau und sagte auch, ich könne alles nachvollziehen und werde in Zukunft damit wohl auch klarkommen müssen. Ausserdem würde ich keine solche Frage stellen, wenn ich nicht an Veränderungen interessiert wäre. 🙄



  • Scheppertreiber schrieb:

    ...Die Rechner sind heute dermaßen schnell, daß der
    Unterschied zwischen einer Variable und einem #define nicht mehr auffällt....

    😮 😮
    äh "Schnelligkeit" ist eigentlich nie ein Thema zwischen "Variable" und "#define" ... (allein schon, weil der Compiler sowieso Konstanten "direkt einsetzen" kann).
    Viel wesentlicher ist, dass #defines
    a) "dumme Textersetzung" machen und damit zu ärgerlichen Fehlern führen können und
    b) nicht "adressierbar" sind, weswegen man sie oftmals nicht verwenden kann:

    void f(int const&);
    
    int const i1 = 2;
    #define i2 2
    
    int main() {
       f(i1); // geht
       f(i2); // geht nicht
    

    sizeof() tut's nicht und eine Menge anderer Dinge ...

    Ergo: #define da, wo man Textersetzung braucht und nicht als "Konstanten" ... schließlich hat C++ ja Konstanten dafür.

    Gruß,

    Simon2.



  • Ich weiß ja nicht, ob das Compilerspezifisch ist, aber ich glaube nicht:
    alles was du genannt hast geht.
    Ersteres, weil man als konstante Referenz durchaus auch ein Literal übergeben kann(allerdings natürlich nur, wenn sie auch konstant ist).
    Ein Zahlenliteral ist afaik auch immer vom Typ Integer und wird von sizeof auch so angesehen. Eine Gleitkommazahl immer ein Double, ein String immer ein const char* und ein Charliteral immer ein char*.


  • Mod

    Simon2 schrieb:

    f(i2); // geht nicht
    

    was geht nicht?

    Simon2 schrieb:

    sizeof() tut's nicht

    tut was nicht?

    Präprozessormakros ignorieren Scopes, werten ihre Argumente ggf. mehrfach aus (was fast immer unerwünscht ist) und sind für den Linker und in der Regel auch für den Debugger unsichtbar, was die Benutzung von Letzterem erheblich erschweren kann.
    "Schnelligkeit" ist außerhalb einer konkreten Implementation und eines konkreten Programmes ein weitgehend bedeutungsloser Begriff.



  • Hi Simon2,

    solche Probleme sollte man im Griff haben.

    Kennt man den Unterschied zwischen einem Präprozessor und einen Compiler ist
    der rest auch trivial. Mir ist nicht erklärbar, daß da ständig solche Grundsatzdiskussionen
    auftauchen.

    Ein Präprozessor hat mit der Programmiersprache überhaupt rein gar nix zu tun.

    Grüße Joe.



  • Hat jemand noch ein weiteres Argument, das gegen die globalen Variabeln spricht?
    Nicht dass mich die bisherigen zu wenig überzeugt hätten, das waren sogar ziemlich gute Argumente 😃

    Nur falls jemand noch etwas hinzufügen möchte oder es noch einen anderen wichtigen Grund gegen globale Variabeln gibt...



  • Scheppertreiber schrieb:

    ...Mir ist nicht erklärbar, daß da ständig solche Grundsatzdiskussionen auftauchen...

    Mir auch nicht ... aber da Du es mit Deinem Plädoyer für #defines getan hast, dachte ich, darauf antworten zu sollen...

    Scheppertreiber schrieb:

    ...Ein Präprozessor hat mit der Programmiersprache überhaupt rein gar nix zu tun....

    Eben.
    Und da die Sprache bereits Konstanten kennt, sehe ich keinen Grund, diese Funktionälität auf "#defines" auszulagern.

    Gruß,

    Simon2.



  • JustAnotherNoob schrieb:

    ...
    alles was du genannt hast geht.
    ...

    camper schrieb:

    Simon2 schrieb:

    f(i2); // geht nicht
    

    was geht nicht?

    Simon2 schrieb:

    sizeof() tut's nicht

    tut was nicht?
    ...

    Hupps ! 🙄

    OK, mein ursprüngliches Beispiel war auch ein anderes, das ich hier auch mal zur Frage stelle:

    void f(int const* p) { cout << static_cast<void const*>(p); }
    
    int const i1 = 2;
    #define i2 2
    
    int main() {
       f(&i1); // ??
       f(&i2); // ??
    
    // ... oder ganz erste Idee:
       int const* arr[] = { &i1, &i2 };
    

    ... und wie immer, wenn man sich in letzter Sekunde noch mal spontan umentscheidet ("das geht ja noch einfacher"), übersieht man auf die Schnelle, dass es doch nicht "dasselbe" ist.
    Spätestens, wenn man int, char, double, & Co verlässt und sich sowas zuwendet:

    struct A { A(int, string); };
    

    dürften "Konstenten via Präprozessor" schon schwerer werden, oder ?
    (OK, man könnte auf temp-Variablen ausweichen)

    Gruß,

    Simon2.


Anmelden zum Antworten