Tags

  • AWS (7)
  • Apigee (3)
  • ArchLinux (5)
  • Array (6)
  • Backtracking (6)
  • BinarySearch (6)
  • C++ (19)
  • CI&CD (3)
  • Calculus (2)
  • DesignPattern (43)
  • DisasterRecovery (1)
  • Docker (8)
  • DynamicProgramming (20)
  • FileSystem (11)
  • Frontend (2)
  • FunctionalProgramming (1)
  • GCP (1)
  • Gentoo (6)
  • Git (16)
  • Golang (1)
  • Graph (10)
  • GraphQL (1)
  • Hardware (1)
  • Hash (1)
  • Kafka (1)
  • LinkedList (13)
  • Linux (27)
  • Lodash (2)
  • MacOS (3)
  • Makefile (1)
  • Map (5)
  • MathHistory (1)
  • MySQL (21)
  • Neovim (11)
  • Network (67)
  • Nginx (6)
  • Node.js (33)
  • OpenGL (6)
  • PriorityQueue (1)
  • ProgrammingLanguage (9)
  • Python (10)
  • RealAnalysis (20)
  • Recursion (3)
  • Redis (1)
  • RegularExpression (1)
  • Ruby (19)
  • SQLite (1)
  • Sentry (3)
  • Set (4)
  • Shell (4)
  • SoftwareEngineering (12)
  • Sorting (2)
  • Stack (4)
  • String (2)
  • SystemDesign (13)
  • Terraform (2)
  • Tree (24)
  • Trie (2)
  • TwoPointers (16)
  • TypeScript (3)
  • Ubuntu (4)
  • Home

    Understanding the meaning of lvalues and rvalues in C++

    Published Aug 02, 2019 [  C++  ]

    Lvalues and rvalues: a friendly definition

    In C++ an lvalue is something that points to a specific memory location.

    A rvalue is something that doesn’t point to anywhere.

    In general, rvalues are temporary and short lived, while lvalues live a longer life since they exist as variables. It’s also fun to think of lvalues as containers and rvalue as things contained in the container.

    int x = 666;
    

    Here 666 is an rvalue; a number (technically a literal constant) has no specific memory address, except for some temporary register while the program is running. That number is assigned to x, which is a variable. A variable has a specific memory location, so its an lvalue. C++ states that an assignment requires an lvalue as its left operand: this is perfectly legal;.

    int* y = &x;
    

    Here I’m grabbing the memory address of x and putting it into y, through the address-of operator &. It takes an lvalue argument and produces an rvalue. This is another perfectly legal operation: on the left side of the assignment we have an lvalue (a variable), on the right side an rvalue produced by the address-of operator.

    int y;
    666 = y; //error!
    

    The technical reason is that 666, being a literal constant - so an rvalue, doesn’t have a specific memory location. y is assigned nowhere.

    int* y = &666; // error
    

    The & operator wants an lvalue in input, because only an lvalue has an address that & can process.

    Functions returning lvalues and rvalues

    Left operand of an assignment must be an lvalue.

    int setValue(){
        return 6;
    }
    
    setValue() = 3; // error
    

    setValue() returns an rvalue (the temporary number 6), which cannot be a left operand of assignment.

    int global = 100;
    
    int& setGlobal(){
        return global;
    }
    
    setGlobal = 400;    // ok
    

    It works because setGlobal returns a reference.

    Lvalue to rvalue conversion

    An lvalue may get converted to an rvalue. According to the C++ specification, it takes two rvalues as arguments and return an rvalue.

    int x = 1;
    int y = 3;
    int z = x + y;
    

    x and y have undergone an implicit lvalue-to-rvalue conversion

    Lvalue references

    int y = 10
    int& yref = y;
    yref++;         // y is now 11
    

    yref is of type int&: a reference to y. It’s called an lvalue reference

    void fnc(int& x){
    
    }
    
    int main(){
        fuc(10);    // error
        int x = 10;
        fnc(x);     // ok
    }
    

    Const lvalue reference to the rescue

    You are allowed to bind a const lvalue to an rvalue

    // this
    const int& ref = 10;    // OK!
    
    // would translate to
    int __internal_unique_name = 10;
    const int& ref = __internal_unique_name;
    
    void fnc(const int& x){
    
    }
    
    int main(){
        fnc(10);    // ok
    }
    

    References: https://www.internalpointers.com/post/understanding-meaning-lvalues-and-rvalues-c