Frage bzgl. L-und R-Wert-Referenzen und Operaten



  • Eine Expression aus einer Funktion die eine Referenz zurückgibt ist ein lvalue. Ganz egal, wo sie steht.



  • @Swordfish aber wenn der compiler aus der Operator Methode/Funktion rausspringt, dann muss er ja zwangslaeufig die zurückgegebene String& Referenz im Speicher halten, sodass diese doch in dem Falle s3 = s1+s2 ein R-Wert waere, oder nicht? Denn wenn ich eine funktion haette Bsp:
    func(int a, int b){
    return a+b;
    }
    diese rufe ich in der main auf
    int main(){
    int c = func(4,4);
    return 0;
    }
    dann ist es doch so, dass der Rueckgabewert in diesem Fall die Zahl 8(4+4) doch ein R-Wert waere, der nur kurzfristig im Speicher gehalten wird, oder irre ich da?



  • Das hat damit erstmal nichts zu tun. Wenn eine Funktion eine Referenz zurückgibt, kannst du das durchaus als lvalue benutzen (bzw. auf der linken Seite einer Zuweisung). Ob das dann funktioniert, ist eine andere Frage.



  • @tes32 "muss im Speicher behalten" ... hör bitte auf so zu denken. Ein Compiler muss einen feuchten kehrricht. In deinem Beispiel darf er auch dein c direkt mit 8 initialisieren ohne func() jemals aufzurufen (davon ausgehend, daß c später noch verwendet wird. Wenn nicht gibts eventuell gar kein c.). Wie eine Expression verwendet wird bestimmt nicht, von welcher Value-Kategorie sie ist.



  • @Swordfish koenntest du mir dann bitte ein Beispiel geben, wann genau ein R-Wert Value entsteht?
    Denn das Standartbeispiel ist ja meistens int a = 4. Dann sagen die Lehrbuecher, 4 ist ein R-Wert. Wie erzeuge ich denn einen R-Wert bei z.B Objekten, wenn nicht ueber Funktionen?



  • Da du so auf funktionen und deren Rückgabetyp fixiert bist:

    int foo() { return 42; }
    
    // ...
    
    foo(); // ist ein rvalue. genauer ein prvalue.
    

    Guckst du bitte http://www.stroustrup.com/terminology.pdf



  • @Swordfish Ok, der Aufruf von foo(); ist ein r bzw pr value. Ich habe folgenden Beispielcode
    #include "VektorClass.h"
    VektorClass& func(VektorClass& a){
    return a;
    }
    int main(){
    VektorClass b;
    VektorClass &c = b;
    VektorClass{func(c)};
    return 0;
    }

    Dann Frage ich mich wieso VektorClass{func(c)}; nicht den Verschiebekonstruktor aufruft bzw. warum func(c) keinen r Wert liefert?
    Denn natürlich ist der Rückgabewert ein LValue, aber es ist ja namenlos(nach stroustrup also (Im:
    does not have identity and can be moved from)) und ruft den Copy Konstruktor auf? Und einen prValue wuerde dann func(c); erezugen? Wie ist es denn dann möglich in meinem Beispiel den Verschiebekonstruktor aufzurufen? Dieser erwartet ja VektorClass(Vektor&& a)?



  • Schau mal im C++-Standard nach, Kapitel 3.10 (bei C++14) oder 6.10 (C++17):

    (aus C++14)

    An rvalue (so called, historically, because rvalues could appear on the right-hand side of an assignment
    expression) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associated
    with an object.



  • @tes32 Würdest du bitte Code in deinen Beiträgen ordentlich formatieren? Danke.

    Zu deinem Beispiel: Da brauchen wir garnichtmal von irgendwelchen Value-Kategorien reden/wissen um zu schnallen, warum da nicht gemoved werden kann. Das was deine func() zurückgibt ist eine Referenz auf b. b kann nicht einfach so aufhören zu existieren indem von b gemoved würde.



  • @Swordfish

    #include "VektorClass.h"
    VektorClass func(VektorClass& a){
    	return a;
    }
    int main(){
    	VektorClass b;
    	VektorClass &&c = func(b);
    	return 0;
    }
    
    
    Hier wuerde es sich dann aber um einen rvalue handeln, da dieses zerstoert werden kann? Und bei Operatoren die z.B ein VektorClass& zurueckgeben, da waere es dann doch auch das gleiche, oder nicht?


  • @wob Vielen Dank, haettest du vllt. einen Link? Oder meinst du die Website
    https://isocpp.org/std/the-standard



  • Der letzte Standard Draft: http://eel.is/c++draft/basic.lval

    Hier wuerde es sich dann aber um einen rvalue handeln, da dieses zerstoert werden kann?

    Wenn du das gelesen hast, hörst du bitte auf solche sachen zu sagen.

    Und bei Operatoren die z.B ein VektorClass& zurueckgeben, da waere es dann doch auch das gleiche, oder nicht?

    Nein, es ist bezüglich der Value-Kategorie ein Unterschied, ob eine Funktion eine Referenz oder einen Value-Typ zurückgibt.



  • @Swordfish

    #include "VektorClass.h"
    VektorClass func(VektorClass& a){
       return a;
    }
    int main(){
       VektorClass b;
       VektorClass &&c = func(b);
       return 0;
    }
    

    Nach Standard bin ich mir nicht sicher ob func(b) jetzt
    1.1 A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function.
    ist, da der glvalue eine expression ist dessen valuation die Identitaet des Objekts bestimmt, dürfte hier nicht der Fall sein.
    oder
    1.2
    A prvalue is an expression whose evaluation initializes an object or a bit-field, or computes the value of an operand of an operator, as specified by the context in which it appears.
    Muesste der Fall sein, da func(b);
    mit

    VektorClass &&c = func(b);
    

    &&c intilisiert bzw. ein anderes Objekt intialisieren koennte, ist das so richtig?

    #include "VektorClass.h"
    VektorClass& func(VektorClass& a){
    	return a;
    }
    int main(){
    	VektorClass b;
    	VektorClass &c = b;
            VektorClass d {func(c)};
    	return 0;
    }
    

    Tritt hier

    4

    [ Note: An expression is an xvalue if it is:

    (4.1)
    the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type ([expr.call]),
    

    auf?
    Aber mein return Typ ist eine lvalue Referenz und damit ist das ausgeschlossen. Ich weiß nicht um welchen Punkt es sich hier nach Standard handelt 😕
    Was ich mir noch vorstellen koennte:
    (1.1)
    A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function.
    Die Auswertung er Funktion fuehrt ja zu der Identitaet meines Objectes d.
    (1.3)
    An xvalue is a glvalue that denotes an object or bit-field whose resources can be reused (usually because it is near the end of its lifetime).
    (1.4)
    An lvalue is a glvalue that is not an xvalue.
    Jetzt wuerde ich sagen es gilt 1.3 und somit ist es ein xvalue, denn das obejt hat das Ende seiner Lebenszeit, dadurch das es zurückgegeben wird, erreicht.





  • @tes32 sagte in Frage bzgl. L-und R-Wert-Referenzen und Operaten:

    #include "VektorClass.h"
    

    Ich weiß nicht, wozu wir das brauchen?

    Du hast zwei Beispiele gebracht:

    1. int func(int &a){ return a; }
      
      // ...
      
      int b;
      int &&c = func(b);
      

    und

    1. int& func(int &a) { return a; }
      
      // ...
      
      int b;
      // int &c = b;  // die Zeile ist überflüssig. Läuft aufs selbe raus wenn wir
      int d { func(b) };  // hier gleich b an func() übergeben.
      

    ´
    Ja, in 1. ist func(b) ein prvalue.

    In 2.

    Every expression belongs to exactly one of the fundamental classifications in this taxonomy: lvalue, xvalue, or prvalue.


    Hm. lvalue?

    An lvalue is a glvalue that is not an xvalue.

    Maybe Baby. (Wegen @SeppJ darf ich keine OT Witze mehr machen. Dann eben OnTopic ^^)


    glvalue?

    A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function.

    Si. Eine Referenz auf ein Objekt bestimmt seine Identität.


    xvalue?

    (4.1) the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type ([expr.call]),

    Nope.

    (4.2) a cast to an rvalue reference to object type ([expr.dynamic.cast], [expr.static.cast], [expr.reinterpret.cast], [expr.const.cast], [expr.cast]),

    Nope.

    (4.3) a subscripting operation with an xvalue array operand ([expr.sub]),

    Nope.

    (4.4) a class member access expression designating a non-static data member of non-reference type in which the object expression is an xvalue ([expr.ref]), or

    Nope.

    (4.5) a .* pointer-to-member expression in which the first operand is an xvalue and the second operand is a pointer to data member ([expr.mptr.oper]).

    Nope.


    Kein xvalue also lvalue.


    (Ich hoffe die letzten 5 genannten Punkte werden normativ. Sonst wirds echt schwer zu argumentieren 😕 )

    Was ich mich die ganze Zeit frage: Was bringt dir dieses Wissen nun? Das einzig spannende daran ist RVO. IIRC hat sich das zwischen C++11 und C++17 nochmal geändert.

    // edit: Vielleicht hilft dir der Artikel von Barry Revzin. (Inklusive Code um die Value Category einer Expression zu bestimmen.)



  • @Swordfish Ok, vielen Dank, dann sind mir einige Dinge klarer geworden. 🙂


Anmelden zum Antworten