Initialisierung von Variablen



  • #include <iostream>
    
    using namespace std;
    int addiere_5(int);     //Deklaration des Funktionsprototypen
    
    int main()
    {
        int erg, i=0;
        cout<<i<<" = Wert von i\n";
        //cout<<erg<<" = Wert von erg "<<endl;
        erg=addiere_5(i);
        cout<<erg<<" = Ergebnis von addiere_5\n";
        cout<<i<<" = i unverändert!\n";
    
    }
    
    int addiere_5(int x)   //Funktionsdefinition
    {
        x+=5;
        return x;
    }
    

    In diesem Programmbeispiel wird die Variable erg nicht initialisiert.
    Kann man das kritisieren? Oder ist eine Initialisierung hier nicht notwendig?



  • Da die erste Verwendung der Variablen die Zuweisung erg=addiere_5(i); , geht das (hier) schon in Ordnung. Allerdings solltest du dir überlegen, ob du die Variable vorher überhaupt benötigst - und die Definition entsprechend nach hinten verlagern.



  • redrew99 schrieb:

    Kann man das kritisieren? Oder ist eine Initialisierung hier nicht notwendig?

    Ja, das kann man kritisieren, auch wenn eine Initialisierung nicht notwendig erscheint. Man könnte sagen, die Variable ist nicht initialisiert und enthält irgendwelchen Müll, eben das, was gerade auf dem Stack ist und das ist nicht gut.



  • Ich kritisiere die Nicht-Initialisierung keineswegs.
    Grund: Spart Code, spart Resourcen (CPU und Speicherplatz der Executable auf der Harddisk)



  • Zu kritisieren wäre in diesem Fall, dass Du es nicht so geschrieben hast:

    int main()
    {
        int i = 0;
        cout << i << " = Wert von i\n";
        int erg = addiere_5(i);
        cout << erg << " = Ergebnis von addiere_5\n";
        cout << i << " = i unverändert!\n";
    }
    

    Gewöhne Dir an, die Variablen erst dann zu definieren, wenn du sie brauchst und nach Möglichkeit auch gleichzeitig richtig initialisierst. Bei anderen Typen (wie zB std::string) gibt es durchaus Performanz-Unterschiede; denn der Compiler darf in einer Situation wie dieser:

    string foo()
    {
      string x = "123";
      return x;
    }
    
    int main()
    {
      string y = foo();
    }
    

    alle möglichen string-Kopiervorgänge komplett wegoptimieren (es gibt dann genau ein string-Objekt, also, x und y beziehen sich dann auf dasselbe Objekt). Im folgenden Beispiel...

    int main()
    {
      string y;
      y = foo();
    }
    

    ...geht das nämlich nicht mehr. Hier wird y default-konstruiert, x erzeugt und dann wird y x zugewiesen. In C++03 bedeutet das eine unnötige Kopier-Zuweisung.

    Außerdem kannst Du so auch Programmierfehler vermeiden, weil Du dann einfach weniger "uninitialisierte" Variablen hast.



  • Wobei doch einige std::string -Implementierungen COW haben. Aber ansonsten hast du natürlich recht 👍 .



  • EOutOfResources schrieb:

    Grund: Spart Code, spart Resourcen (CPU und Speicherplatz der Executable auf der Harddisk)

    Ich glaube, das ist ein Irrtum oder zumindest man kann es so nicht verallgemeinern. Die Initialisierungswerte werden vom Compiler "wegoptimiert", dort wo sie wegoptimiert werden können.


  • Mod

    abc.w schrieb:

    EOutOfResources schrieb:

    Grund: Spart Code, spart Resourcen (CPU und Speicherplatz der Executable auf der Harddisk)

    Ich glaube, das ist ein Irrtum oder zumindest man kann es so nicht verallgemeinern. Die Initialisierungswerte werden vom Compiler "wegoptimiert", dort wo sie wegoptimiert werden können.

    Und krümelkacker hat gerade ein Beispiel gezeigt, wo er es nicht kann.



  • Es geht hier um den Datentyp int. Wozu soll man den jedesmal gleich initialisieren, wenn eine Zuweisung später sichergestellt ist? 😕 Mit in einer Funktion mehrfach benötigten Laufvariablen in Schleifen wie i,j, ... macht man aus Gründen der Bequemlichkeit auch nicht! Die Verwendung einer nicht zuvor initialisierten oder zugewiesenen Variable sollte jeder Compiler als Warnung sicher anmeckern! 🕶
    Die Frage erscheint mir 'peanut', an der man sich beliebig hochziehen kann! 😃



  • SeppJ schrieb:

    abc.w schrieb:

    EOutOfResources schrieb:

    Grund: Spart Code, spart Resourcen (CPU und Speicherplatz der Executable auf der Harddisk)

    Ich glaube, das ist ein Irrtum oder zumindest man kann es so nicht verallgemeinern. Die Initialisierungswerte werden vom Compiler "wegoptimiert", dort wo sie wegoptimiert werden können.

    Und krümelkacker hat gerade ein Beispiel gezeigt, wo er es nicht kann.

    krümelkacker hat ein Beispiel gezeigt, das mit dem Thema nichts zu tun hat.


  • Mod

    abc.w schrieb:

    krümelkacker hat ein Beispiel gezeigt, das mit dem Thema nichts zu tun hat.

    Tada!

    string y;
    y = "abc";
    

    Setze zur Not irgendeine andere Klasse als string ein, zum Beispiel etwas selbstgeschriebenes bei dem der Compiler den Konstruktor nicht sieht. Oder auch so:

    string nicht_lokal_deklariert;
    if (bedingung)
     {
       benutze(nicht_lokal_deklariert);
     }
    // Benutze den string nicht weiter
    

    Da muss ein Compiler schon ganz schön schuften, um das zu optimieren, würde ich mich nicht drauf verlassen. Punkt ist, dass komplexe Konstruktoren nicht so leicht zu optimieren sind.



  • berniebutt schrieb:

    Es geht hier um den Datentyp int. Wozu soll man den jedesmal gleich initialisieren, wenn eine Zuweisung später sichergestellt ist? 😕

    Warum nicht erst deklarieren, wenn man ihn initialisieren kann? Klar, dass das nicht immer geht, aber das hier wäre so ein typisches Beispiel. Ein anderes Beispiel wäre Konstruktor-Initialisierungsliste vs. nachträgliche Zuweisung. Aber ich wiederhole eigentlich nur krümelkackers Aussage.

    berniebutt schrieb:

    Mit in einer Funktion mehrfach benötigten Laufvariablen in Schleifen wie i,j, ... macht man aus Gründen der Bequemlichkeit auch nicht!

    Natürlich initialisiert man Schleifenvariablen gleich. Oder deklarierst du diese etwa ausserhalb der Schleife?



  • Nexus schrieb:

    berniebutt schrieb:

    Mit in einer Funktion mehrfach benötigten Laufvariablen in Schleifen wie i,j, ... macht man aus Gründen der Bequemlichkeit auch nicht!

    Natürlich initialisiert man Schleifenvariablen gleich. Oder deklarierst du diese etwa ausserhalb der Schleife?

    JA, das mache ich nicht nur aus alter Gewohnheit so. In einer Funktion mit mehreren aufeinander folgenden Schleifen wäre jede lokale Deklaratíon mit Initialisierung unsinnig, obwohl möglich. 🙂
    Mit Performance und Speicherbedarf ist da nicht viel zu holen, es macht nur mehr Schreibarbeit! 😃

    Wie sagt der Lateiner? 'Suum quique!'

    Es bleibt die Aussage: 'Sobald eine Variable benutzt werden kann, muss diese einen selbst kontrollierten Wert haben.' 😡



  • berniebutt schrieb:

    In einer Funktion mit mehreren aufeinander folgenden Schleifen wäre jede lokale Deklaratíon mit Initialisierung unsinnig, obwohl möglich.

    Wieso unsinnig? Du hältst damit den Scope lokal. Erstens siehst du so unmittelbar die Deklaration, zweitens verhinderst du, dass die Variable versehentlich ausserhalb der Schleife verwendet wird.

    berniebutt schrieb:

    Mit Performance und Speicherbedarf ist da nicht viel zu holen, es macht nur mehr Schreibarbeit! 😃

    Stimmt, die Schreibarbeit. Dem kann ich wohl nichts mehr entgegen setzen. Und wenn ich erst dran denke, wie oft ich gleich mehrere Schleifen nacheinander in einer Funktion habe! 😮



  • EOutOfResources schrieb:

    Ich kritisiere die Nicht-Initialisierung keineswegs.
    Grund: Spart Code, spart Resourcen (CPU und Speicherplatz der Executable auf der Harddisk)

    Oh boy...



  • hustbaer schrieb:

    Oh boy...

    Ich sagte nie, dass es relevant ist oder nicht wegoptimiert werden kann 😉 .



  • krümelkacker schrieb:

    Zu kritisieren wäre in diesem Fall, dass Du es nicht so geschrieben hast:

    int main()
    {
        int i = 0;
        cout << i << " = Wert von i\n";
        int erg = addiere_5(i);
        cout << erg << " = Ergebnis von addiere_5\n";
        cout << i << " = i unverändert!\n";
    }
    

    Gewöhne Dir an, die Variablen erst dann zu definieren, wenn du sie brauchst und nach Möglichkeit auch gleichzeitig richtig initialisierst. Bei anderen Typen (wie zB std::string) gibt es durchaus Performanz-Unterschiede; denn der Compiler darf in einer Situation wie dieser:
    [cpp]

    Außerdem kannst Du so auch Programmierfehler vermeiden, weil Du dann einfach weniger "uninitialisierte" Variablen hast.

    Danke für den Tip. Der Code ist nicht von mir, sondern aus einem Lehrbuch.
    Da ich an verschiedenen Stellen bislang nur gelesen habe, daß man Variablen bei Definition auch initialisieren sollte, wollte ich mal wissen, wie die Abweichung von der Regel in diesem Programmbeispiel einzuordnen ist.


Anmelden zum Antworten