Zahl als Referenz ?!



  • Hallo zusammen,
    ich habe eine Fragen bezüglich Funktionen, die als Parameter eine Referenz bekommen. Das hier geht wohl nicht:

    #include <iostream>
    using namespace std;
    
    int addiere(int& a, int&b)
    {
    	return a+b;
    }
    
    int main () 
    {
    	cout << verdopple(5,5);
    
    	return 0;
    }
    

    Ich frage mich nur, warum das nicht geht. Ich dachte, dass auch einfache Zahlen als Referenz übergeben werden können, da der Compiler eine temporäre Variable anlegt, die die Werte speichern. Ist das nicht so?

    Vielen Dank
    lg, freakC++



  • Ein temporäres Objekt kann nicht an eine non- const Referenz gebunden werden.
    Verwende doch const Referenzen.

    Simon



  • Für normale Zahlen brauchst du const referenzen... Oder wie willst du die konstante Zahl 5 auf 4 ändern???

    :hoppschwiiz: :hoppschwiiz: :hoppschwiiz: :hoppschwiiz:



  • Jaa, stimmt! Da war was. Danke! Dennoch ist mir das noch nicht so ganz klar. Warum ist das const hier absolut notwendig? Es gibt doch keine Möglichkeit die übergebene Zahl wieder zu ändern. Sie ist doch sowieso konstant. Wird denn mit const eine temporäre Variable angelegt?

    Vielen Dank
    lg, freakC++

    :schland: :schland: :schland:



  • Du übergibst der Funktion in deiner main ja keine Variablen, sondern im Endeffekt Referenzen auf Literale. Und diese sind konstant, was deine Funktion nicht ist. Ob du die dann in der Funktion änderst oder nicht ist ja egal, es zählt erst einmal nur die Signatur.

    Was ich aber lustig finde ist das das geht:

    #include <iostream>
    
    int &narf(const int &a)
    {
      return ++const_cast<int&>(a);
    }
    
    int main()
    {
      std::cout << narf(4) << std::endl;
    }
    

    😃



  • freakC++ schrieb:

    Das hier geht wohl nicht:

    int addiere(int& a, int&b)
    {
    	return a+b;
    }
    
    void foo() 
    {
    	verdopple(5,5);
    }
    

    Ich frage mich nur, warum das nicht geht.

    Das Beispiel, mit dem man begründet, warum "RValues" nicht an "non-const LValue"-Referenzen gebunden werden können, ist das hier:

    void inc(long & i)
    {
      ++i;
    }
    
    void foo()
    {
      int k = 3;
      inc(k); // implizite Konvertierung von int->long.  Glücklicherweise
              // kann die Referenz i nicht mit einem RValue initialisiert
              // werden.  Wenn das doch so ginge, dann würde der Wert des
              // temporären  long-Objekts  inkrementiert  und k verändert 
              // sich nicht.  Das liegt wahrscheinlich nicht im Sinne des
              // Programmierers.
    }
    


  • Fellhuhn schrieb:

    Was ich aber lustig finde ist das das geht:

    Das ist undefiniert, weil du das const von einem konstanten Speicherbereich wegcastest.



  • Michael E. schrieb:

    Fellhuhn schrieb:

    Was ich aber lustig finde ist das das geht:

    Das ist undefiniert, weil du das const von einem konstanten Speicherbereich wegcastest.

    Bei "Undefiniert" wird es doch erst richtig lustig. 🙂



  • Fellhuhn schrieb:

    Was ich aber lustig finde ist das das geht:

    #include <iostream>
    
    int &narf(const int &a)
    {
      return ++const_cast<int&>(a);
    }
    
    int main()
    {
      std::cout << narf(4) << std::endl;
    }
    

    😃

    Naja, kurz bevor die Referenz initialisiert wird, wird ein temporäres int-Objekt erzeugt. Die Referenz verweist dann auf dieses Objekt. Du veränderst dieses Objekt mit Hilfe eines const_casts und nach dem vollständigen Ausdruck in main, wird das int-Objekt wieder zerstört. Das müsste eigentlich -- wenn es auch unschön aussieht -- in Ordnung sein, also kein undefiniertes Verhalten hervorrufen. Das müsste äquivalent zu

    {
      int temp = 4;
      std::cout << narf(temp) << std::endl;
    }
    

    sein.

    @Michael E.: Im Falle, dass ich mich irre und Fellhuhns Code äquivalent zu

    {
      [b]const[/b] int temp = 4;
      std::cout << narf(temp) << std::endl;
    }
    

    ist, dann hast Du natürlich Recht, da hier der const_cast nicht angewendet werden darf.



  • Ich will mich auch nicht zu weit aus dem Fenster lehnen, weil ich nicht die passende Stelle im Standard habe, aber äquivalent zum ersten Code kann es nicht sein, weil sonst auch der Code des OP legal wäre.



  • freakC++ schrieb:

    Hallo zusammen,
    ich habe eine Fragen bezüglich Funktionen, die als Parameter eine Referenz bekommen. Das hier geht wohl nicht:

    #include <iostream>
    using namespace std;
    
    int addiere(int& a, int&b)
    {
    	return a+b;
    }
    
    int main () 
    {
    	cout << verdopple(5,5);
    	
    	return 0;
    }
    

    Ich frage mich nur, warum das nicht geht. Ich dachte, dass auch einfache Zahlen als Referenz übergeben werden können, da der Compiler eine temporäre Variable anlegt, die die Werte speichern. Ist das nicht so?

    Vielen Dank
    lg, freakC++

    Verzichte auf Referenzen, wenn Du die Werte sowieso nicht ändern willst. Also ganz primitiv:

    #include <iostream>
    using namespace std;
    
    int addiere (int a, int b)
    {
    	return a+b;
    }
    
    int main () 
    {
    	cout << addiere (5,5);
    
    	return 0;
    }
    

    Referenzen sind "bessere Zeiger". In Deinem Fall also nicht nötig.



  • Michael E. schrieb:

    Ich will mich auch nicht zu weit aus dem Fenster lehnen, weil ich nicht die passende Stelle im Standard habe, aber äquivalent zum ersten Code kann es nicht sein, weil sonst auch der Code des OP legal wäre.

    Nun, darum geht es ja gerade. Wer sagt, dass er es nicht ist? Ich habe mal nachgeguckt und die interessante Stelle ist 8.5.3/5:

    A reference to type cv1 T1 is initialized by an expression of type cv2 T2 as follows:

    • Otherwise, a temporary of type “cv1 T1” is created and initialized from the initializer expression using the rules for a non-reference copy initialization (8.5). […]

    Ich denke, dadurch, dass das cv1 beim Typ des temporären Objekts dabei ist und hier in diesem Fall cv1=const ist, wird der const_cast "illegal" (ruft also UB hervor).


Log in to reply