DEV Community

Karan Hejmadi
Karan Hejmadi

Posted on

Understanding lvalues and rvalues in C++

If you have worked with C++, you might've come across errors like "Expression must be a modifiable lvalue". This post will give you a clear understanding on what those terms mean.

In simple terms, lvalue is something that has a memory address and rvalue doesn't.

An easy example.

int a = 10;
Enter fullscreen mode Exit fullscreen mode

Here, 10 is rvalue and a is lvalue. Simply because 10 does not have any location. It is just a temporary constant which the compiler creates to assign it to a;

Key points to note

  • An rvalue cannot be assigned any value
int a;
10 = a; // NOT VALID!
Enter fullscreen mode Exit fullscreen mode
  • An lvalue can be assigned to another lvalue.
int a = 10;
int b = a; // VALID
Enter fullscreen mode Exit fullscreen mode
  • A function that returns a rvalue is also a rvalue
int getValue() {
  return 10;
}

int main() {
  getValue() = 20; // ERROR
}

Enter fullscreen mode Exit fullscreen mode
  • A function that returns a lvalue is also a lvalue
int& getValue() {
  static int a = 10;
  return a;
}

int main() {
  getValue() = 20; // NO ERRORS.
}

Enter fullscreen mode Exit fullscreen mode

lvalue and rvalue references

This is mainly important when dealing with functions.

  • A lvalue can be taken as a parameter using & operator
void setValue(int& a) {
 // Do something
}
Enter fullscreen mode Exit fullscreen mode
  • A rvalue can be taken as a parameter using && operator
void setValue (int&& a) {
 // Do something
}
Enter fullscreen mode Exit fullscreen mode
  • A const lvalue reference can be assigned to an rvalue
int& a = 10; // NOT VALID
const int& b = 10; // VALID 
Enter fullscreen mode Exit fullscreen mode

This is the reason why int C++ a function that accepts a string reference should always be assigned with const.

// accepts only lvalue
void showFullName_1(string& fullName) {
 cout<<fullName<<endl;
} 

// accepts both lvalue and rvalue
void showFullName_2(const string& fullName) {
 cout << fullName <<endl;
}

// accepts only rvalue
void showFullName_3(string&& fullName) {
 cout << fullName <<endl;
}

int main() {
  string firstName = "john";
  string lastName = "doe";
  string fullName = firstName + lastName; //assigning to an lvalue

  showFullName_1(fullName); //works
  showFullName_1(firstName + lastName); // doesn't work because firstName + lastName is a rvalue

  showFullName_2(fullName); // works
  showFullName_2(firstName + lastName); // works

  showFullName_3(fullName); // doesn't work
  showFullName_3(firstName + lastName); // works

}
Enter fullscreen mode Exit fullscreen mode

Hope this gives you a basic understanding of what lvalues and rvalues are. If you found this helpful please share and comment!

Discussion (0)