Like it!

Join us on Facebook!

Like it!

Understanding the meaning of lvalues and rvalues in C++

A lightweight introduction to a couple of basic C++ features that act as a foundation for bigger structures.

I have been struggling with the concepts of lvalue and rvalue in C++ since forever. I think that now is the right time to understand them for good, as they are getting more and more important with the evolution of the language.

Once the meaning of lvalues and rvalues is grasped, you can dive deeper into advanced C++ features like move semantics and rvalue references (more on that in future articles).

Lvalues and rvalues: a friendly definition

First of all, let's keep our heads away from any formal definition. In C++ an lvalue is something that points to a specific memory location. On the other hand, a rvalue is something that doesn't point 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 rvalues as things contained in the containers. Without a container, they would expire.

Let me show you some examples right away.

int x = 666;   // ok

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.

Then with x, which is an lvalue, you can do stuff like that:

int* y = &x;   // ok

Here I'm grabbing the 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.

However, I can't do the following:

int y;
666 = y; // error!

Yeah, that's obvious. But the technical reason is that 666, being a literal constant — so an rvalue, doesn't have a specific memory location. I am assigning y to nowhere.

This is what GCC tells me if I run the program above:

error: lvalue required as left operand of assignment

He is damn right; the left operand of an assigment always require an lvalue, and in my program I'm using an rvalue (666).

I can't do that either:

int* y = &666; // error!

GCC says:

error: lvalue required as unary '&' operand`

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

Functions returning lvalues and rvalues

We know that the left operand of an assigment must be an lvalue. Hence a function like the following one will surely throw the lvalue required as left operand of assignment error:

int setValue()
    return 6;

// ... somewhere in main() ...

setValue() = 3; // error!

Crystal clear: setValue() returns an rvalue (the temporary number 6), which cannot be a left operand of assignment. Now, what happens if a function returns an lvalue instead? Look closely at the following snippet:

int global = 100;

int& setGlobal()
    return global;    

// ... somewhere in main() ...

setGlobal() = 400; // OK

It works because here setGlobal returns a reference, unlike setValue() above. A reference is something that points to an existing memory location (the global variable) thus is an lvalue, so it can be assigned to. Watch out for & here: it's not the address-of operator, it defines the type of what's returned (a reference).

The ability to return lvalues from functions looks pretty obscure, yet it is useful when you are doing advanced stuff like implementing some overloaded operators. More on that in future chapters.

Lvalue to rvalue conversion

An lvalue may get converted to an rvalue: that's something perfectly legit and it happens quite often. Let's think of the addition + operator for example. According to the C++ specifications, it takes two rvalues as arguments and returns an rvalue.

Let's look at the following snippet:

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

Wait a minute: x and y are lvalues, but the addition operator wants rvalues: how come? The answer is quite simple: x and y have undergone an implicit lvalue-to-rvalue conversion. Many other operators perform such conversion — subtraction, addition and division to name a few.

Lvalue references

What about the opposite? Can an rvalue be converted to lvalue? Nope. It's not a technical limitation, though: it's the programming language that has been designed that way.

In C++, when you do stuff like

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

you are declarying yref as of type int&: a reference to y. It's called an lvalue reference. Now you can happily change the value of y through its reference yref.

We know that a reference must point to an existing object in a specific memory location, i.e. an lvalue. Here y indeed exists, so the code runs flawlessly.

Now, what if I shortcut the whole thing and try to assign 10 directly to my reference, without the object that holds it?

int& yref = 10;  // will it work?

On the right side we have a temporary thing, an rvalue that needs to be stored somewhere in an lvalue.

On the left side we have the reference (an lvalue) that should point to an existing object. But being 10 a numeric constant, i.e. without a specific memory address, i.e. an rvalue, the expression clashes with the very spirit of the reference.

If you think about it, that's the forbidden conversion from rvalue to lvalue. A volatile numeric constant (rvalue) should become an lvalue in order to be referenced to. If that would be allowed, you could alter the value of the numeric constant through its reference. Pretty meaningless, isn't it? Most importantly, what would the reference point to once the numeric value is gone?

The following snippet will fail for the very same reason:

void fnc(int& x)

int main()
    fnc(10);  // Nope!
    // This works instead:
    // int x = 10;
    // fnc(x);

I'm passing a temporary rvalue (10) to a function that takes a reference as argument. Invalid rvalue to lvalue conversion. There's a workaround: create a temporary variable where to store the rvalue and then pass it to the function (as in the commented out code). Quite inconvenient when you just want to pass a number to a function, isn't it?

Const lvalue reference to the rescue

That's what GCC would say about the last two code snippets:

error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'

GCC complains about the reference not being const, namely a constant. According to the language specifications, you are allowed to bind a const lvalue to an rvalue. So the following snippet works like a charm:

const int& ref = 10;  // OK!

And of course also the following one:

void fnc(const int& x)

int main()
    fnc(10);  // OK!

The idea behind is quite straightforward. The literal constant 10 is volatile and would expire in no time, so a reference to it is just meaningless. Let's make the reference itself a constant instead, so that the value it points to can't be modified. Now the problem of modifying an rvalue is solved for good. Again, that's not a technical limitation but a choice made by the C++ folks to avoid silly troubles.

This makes possible the very common C++ idiom of accepting values by constant references into functions, as I did in the previous snipped above, which avoids unnecessary copying and construction of temporary objects.

Under the hood the compiler creates an hidden variable for you (i.e. an lvalue) where to store the original literal constant, and then bounds that hidden variable to your reference. That's basically the same thing I did manually in a couple of snippets above. For example:

// the following...
const int& ref = 10;

// ... would translate to:
int __internal_unique_name = 10;
const int& ref = __internal_unique_name;

Now your reference points to something that exists for real (until it goes out of scope) and you can use it as usual, except for modifying the value it points to:

const int& ref = 10;
std::cout << ref << "\n";   // OK!
std::cout << ++ref << "\n"; // error: increment of read-only reference ‘ref’


Understanding the meaning of lvalues and rvalues has given me the chance to figure out several of the C++'s inner workings. C++11 pushes the limits of rvalues even further, by introducing the concept of rvalue references and move semantics, where — surprise! — rvalues too are modifiable. I will restlessly dive into that minefield in one of my next articles.


Thomas Becker's Homepage - C++ Rvalue References Explained (link)
Eli Bendersky's website - Understanding lvalues and rvalues in C and C++ (link)
StackOverflow - Rvalue Reference is Treated as an Lvalue? (link)
StackOverflow - Const reference and lvalue (link) - Reference declaration (link)

Ru on March 11, 2018 at 00:57
Thank you so much for the explanation.
Alfredo from Mexico on April 22, 2018 at 01:32
Thank you for the explanation!
Rajeev from bangalore on November 20, 2018 at 13:10
Superb explanation, simple neat and clean way to explain , good going
Sameer on November 20, 2018 at 16:55
Such a beautiful explanation!
Thang Bui on December 24, 2018 at 05:33
Thank you.
Raj on February 14, 2019 at 05:55
Thank you. on March 18, 2019 at 06:38
basic but clearly introduction, it help me to review those knowledge i had ten years ago:)
TT on April 17, 2019 at 21:15
Very nice and clear explanation! Thank you.
anastasiia_kos on April 29, 2019 at 10:39
Thanks for such a clear and concise explanation of this topic!
Andong Zhan on May 04, 2019 at 20:00
Thanks for the explanation!
Anil Patil on May 05, 2019 at 19:40
Very clear explanation.
Hareesh Vutla on May 10, 2019 at 02:06
Thanks for a very nice explanation
Camilo Jiménez on May 10, 2019 at 03:12
Thanks, a Little bit longer than i usually find a answer, but it's super clear.
Arsin on May 30, 2019 at 21:34
Many thanks. I learned a lot about the rvalues references!
Wubin on June 03, 2019 at 22:20
Great answer!
James on June 11, 2019 at 02:26
Thanks for this post! Super easy to read, informative, and exactly what I was looking for.
Mash on June 12, 2019 at 23:33
Well presented!!
Arun on June 21, 2019 at 20:19
Thank you for this. I attempted to understand this several times but never gave it the attention it deserved. Thanks for the simplicity and the references, appreciate it.
Sean on June 29, 2019 at 05:28
Good explanation!
Prasad Sardeshmukh on July 23, 2019 at 18:14
Thanks a lot for the details.
Youssef on July 27, 2019 at 21:07
Thank you for the clear and easy to follow explanation.
Shivkumar on August 07, 2019 at 15:31
Thank you!
Kyle on August 07, 2019 at 19:36
Very well written. Thank you so much!
Chau on August 09, 2019 at 09:34
Thank you so much. It's so crystal clear
guo on August 10, 2019 at 07:57
> Can an rvalue be converted to lvalue? Nope.

What about:
> int&& value = 123; ?
Hindounette on August 12, 2019 at 16:54
Thank you for the explanations ! Also thank you for making it crystal clear ! It is indeed easy to understand !
Sandy on August 13, 2019 at 06:56
No one could explain lvalue/rvalue simpler than this. Thank you bro!
Triangles on August 14, 2019 at 12:22
@guo that's a rvalue reference. I wrote about it here:
Swati on August 21, 2019 at 08:09
Thank you so much for the amazing article. Very nicely explained. Would like to read more of your articles! :)
Kusuma K V on August 25, 2019 at 08:36
Thank You for a very clear and easy to understand kind of explanation of the internal working. It helped a lot.
atong on August 30, 2019 at 20:09
thank you!
Muhammad Farhan on September 07, 2019 at 12:39
Indeed you gave us an amazing insight of C++ by explaining these l and r values. Thank you !!
Ying on October 11, 2019 at 18:45
Nice, clear, simple.
James on October 16, 2019 at 08:36
Thank you for the explanation, it is very helpful!
Rathinavelu ( on November 03, 2019 at 12:26
C++ has a lot more Sir, for example glvalue, prvalue, xrvalue in addition to rvalue and lvalue.
Maloy on November 05, 2019 at 22:01
Thank you for this explanation. Very helpful.
Anurag on November 10, 2019 at 17:05
Very simple and insightful explanation
David on November 12, 2019 at 15:40
you said "firts of all" instead of "First of all"
Triangles on November 13, 2019 at 11:42
@David typo fixed. Thank you!
Gan on November 19, 2019 at 09:43
As a beginner of C++, I think this is very helpful.
blackBeard on November 22, 2019 at 01:03
WOW, such great explanation
lvalueBRO on November 29, 2019 at 11:09
Hey man that was a crystal clear explanation.. didn't got this superb explanation anywhere in the books and teachers .. love it
gak on December 06, 2019 at 15:28
Great Explanation!
rValueVoodoo on December 17, 2019 at 10:56
Great Article!
eman on December 24, 2019 at 07:38
Thank you for this article with high readability!
Manish Sogi on December 25, 2019 at 05:26
Great Content!
Bharanidharan Subramani on December 26, 2019 at 10:41
Very Excellent explanations. Great Work. Thanks for making understanding the concepts in clear crystal way. Your explanation are going like a nail in tree.
Bharat on January 07, 2020 at 10:16
Excellent explanation!!
mngl on January 16, 2020 at 21:22
Amisha patel on January 21, 2020 at 17:04
An excellent and concise as well discrete explanation !!
thanks allot...
Amisha patel on January 21, 2020 at 17:19
Zhen Wang on January 24, 2020 at 08:22
An excellent explanation. Just one suggestion that it's better to say prvalue instead of rvalue.
Mousumi on January 27, 2020 at 09:09
Excellent explanation with example
Tanya Kejriwal on January 27, 2020 at 22:11
Very nice and simple explanation. The flow of the article made it so much easier to understand. The code snippets helped too. Thanks!
Ill on January 30, 2020 at 23:49
Wow I've been coding in C++ for so many years and I still get confused by this sometimes. The last part about const& helped me understand why I was getting a compiler error in code I knew should compile. Duh, make my function argument be const& instead of & like I usually do.
alok gupta on February 07, 2020 at 07:45
thanks...great explaination
Sona on February 12, 2020 at 19:46
Excellent explanation
Sona on February 12, 2020 at 19:47
Excellent explanation
Tom Sherlock on February 16, 2020 at 18:14
Could we then say that
lvalue is the contained value and
rvalue is the uncontained value?
An Mai on February 19, 2020 at 00:49
This is excellent! Thank you so much!
Dragan on February 24, 2020 at 00:03
Nice and clear
Triangles on February 26, 2020 at 11:45
@Tom Sherlock why not! and thanks for catching the typos :)
Rénald on March 16, 2020 at 01:59
Thanks a lot, and btw I learnt more about the use of const keyword for function parameters ;)
newraozx on April 01, 2020 at 14:35
The Best expiation I have got ever.... thank you for this
Osama Mhiri on April 02, 2020 at 18:46
thanks a lot, you are great !
junaid on April 02, 2020 at 20:03
very good explaination
Aman Prajapati on April 19, 2020 at 05:41
Very nice explanation!!!!
D on April 19, 2020 at 11:47
great explanation !!!
epic on April 19, 2020 at 21:27
Very clear explanation, keep up the good work!
Vincent on April 30, 2020 at 03:01
Absolutely brilliant! So clear, precise and concise. Thank you!
Sami on May 02, 2020 at 04:43
thank you so much. I appreciate it. Very well-explained!
FiLL on May 05, 2020 at 17:37
Thank you for explanation
biggalicious on May 06, 2020 at 01:20
Awesome!!!!!!!!!!! More please. Greatly appreciated i would be yessir
H on May 16, 2020 at 17:31
perfectly explained, thanks a bunch :)
ibra on May 22, 2020 at 04:55
great contribute to the community, this is the way how the whole humanity grows, congrats!!
Tobi on May 29, 2020 at 10:49
Great writeup.
Please, do for xvalue, glvalue, prvalue
Fubini on June 04, 2020 at 16:31
Thank you from Germany! Nice and clean explanation
just_a_random on June 04, 2020 at 19:26
clear and concise, just what I like! thanks!
anonymous on June 07, 2020 at 08:39
amazing explanation!!
nimbustrr on June 07, 2020 at 09:39
great details
scrat on June 07, 2020 at 13:46
Excellent article. Nice explanation.
dilip on June 07, 2020 at 22:29
can you explain about int &&a = 5; // a legal statement, why
Triangles on June 11, 2020 at 10:21
@dilip that's an rvalue reference (double ampersand). More information here:
Chris on June 11, 2020 at 18:22
Thanks for helping me on this topic, your explanation is crystal clear and easy to follow !
Trent Di on June 25, 2020 at 03:17
Excellent article!

"The ability to return lvalues from functions looks pretty obscure, yet it is useful when you are doing advanced stuff like implementing some overloaded operators. More on that in future chapters.". Has this been written? :D
Triangles on June 28, 2020 at 11:48
Thank you Trent Di! The chapter hasn't been written yet... hold tight! :)
Porco on July 04, 2020 at 03:42
Thank you!
Anirudh on July 28, 2020 at 20:29
Excellent explanation! Nice and clear! Thank You!
NULL on August 05, 2020 at 04:52
Thanks a lot! Your explanation is very clear and detailed!
Opel on August 08, 2020 at 07:19
Thank you for the to the point explanation
rishi on August 11, 2020 at 14:44
really a well explained article.........eagerly waiting for more
sachin on August 12, 2020 at 12:36
Great explanation, now i know cpp better!
Neeraj Sharma on August 15, 2020 at 13:17
Very nicely explained. Thoroughly enjoyed.
Prateek on August 15, 2020 at 15:36
This was much needed!! Thanks
Khang on August 16, 2020 at 12:22
Such an awesome and understandable explaination, thank you so much !
Thang Nguyen on August 22, 2020 at 04:44
Excellent article!

I try to explain the l-value and r-value in the example:

But I received an error on line 38, but line 37 is OK. Can you help me to explain the problems?
Shubham Sharma on August 25, 2020 at 20:23
Amazing!!!! That's the best explanation ever.
Abhirath on September 10, 2020 at 12:59
Finally understood what they mean :)
tin1254 on September 26, 2020 at 19:12
Detailed explanation with easy and intuitive to understand examples!
nnammee_yaknow on October 11, 2020 at 03:34
Thank you so much so detailed God Bless

Lung on November 28, 2020 at 14:20
You just saved my life. Thank you so much!
Nurul TA on December 05, 2020 at 02:04
Good explanation. Thank you.
A human on December 06, 2020 at 19:07
I didn't know that i can use r-value with a const l-value reference. This saved me a countless time on my project. Thank you
Art on December 06, 2020 at 20:43
Nice one - thanks for the write up!
sagar kumar sahoo on December 10, 2020 at 10:23
very beautifully explained, wish to read more of your articles
extabl on January 02, 2021 at 12:43
Great explanation. Thank you!
seb on January 03, 2021 at 22:41
thank you
Tobi on January 13, 2021 at 14:43
Amazing explanation!
Ashima on January 20, 2021 at 15:33
Well explained! Thanks :)
Ravi on January 27, 2021 at 16:19
Easy to understand
Shubham Shinde on February 03, 2021 at 17:27
Very well Explained...!!
Olivier Delbeke on February 07, 2021 at 12:10
Great ! Thanks ! I finally understood this !
Yossi Koren on February 14, 2021 at 11:29
Thanks for the clear description!
daniel on February 15, 2021 at 06:18
Yaz on February 19, 2021 at 23:36
One of the bests explanation I've seen on this topic !! Thanks a lot :)
toilet roll on February 21, 2021 at 05:38
why does GCC have to be male? And you say lvalues point to a memory location but they are likely to be stored in a register
Tawhid from bd on March 07, 2021 at 00:15
Thank you.. Great explanation.. It was truly superb
John on March 08, 2021 at 13:27
You should write a book, very clear. Thank you!
Ding on March 21, 2021 at 03:39
This is the best explanation I have ever seen, the way that you start with the design dillema then go into how it's solved by introducing new concepts is the best way to understand a complex concept in depth. Thank you!
Digvijay on March 23, 2021 at 05:20
Great explanation. Thanks....!!!
Evan on April 06, 2021 at 21:21
Adding on to the list of comments - Absolutely amazing article. I'm just starting to learn cpp and have been confused when coming across these terms lvalue and rvalue. This information is presented in a clear an intuitive manner. The synapses really clicked when I realized that an "lvalue" must be on the left side and a "right" value on the right :)
Mike on April 23, 2021 at 09:18
Thanks, very clear!
Brian on May 18, 2021 at 06:09
Very clear explanation, thank you!
Aurelien on May 25, 2021 at 14:38
Amazing, thank you!
Chenfu on May 30, 2021 at 06:06
Saved my day, thanks
santosh on May 31, 2021 at 19:51
Very good explanation. Thanks
Philippe L on June 04, 2021 at 20:32
Great reminder of C++ programmer of old, that needs sometimes to get his memory refreshed with basic theory.
Zhao on June 15, 2021 at 04:29
Thank you very much!
Amit Saonerkar on June 26, 2021 at 07:56
Great explaination! Really internals which are never explained anywhere
Max on August 10, 2021 at 17:35
Perfect explanation of this complex idiom. Keeps us moving forward
Deto on August 11, 2021 at 12:29
What an explaination! Keep doing thing my friend!
Benjamin on August 30, 2021 at 13:45
So clear and simply explained, thank you for that!
JP on August 31, 2021 at 22:34
Amazing article!
elyulien on September 12, 2021 at 21:04
Thank you, thank you, thank you very much, finally after a long time could understand this
M on September 17, 2021 at 16:13
Thanks, it is amazing!
Troy on September 23, 2021 at 08:03
Very thorough explanation.
Haj on October 05, 2021 at 17:25
Very nice!
Ali on October 14, 2021 at 15:36
Thanx ...just when i needed it most
yamero on October 18, 2021 at 15:06
Wow, just wow. Such a simple explanation of a concept thats been bugging me for so long. Bro you are a genius.
Amanu on October 19, 2021 at 18:48
This was what I need, Thanks for detailed explanations!
David on November 06, 2021 at 12:08
Thank you, perfect explanations and tricky cases that may be asked in an interview
iremc on November 07, 2021 at 15:08
That was quite helpful for my exam. Thanks a lott !!
Alireza on November 14, 2021 at 22:01
you solved me one of my very first questions since I started to learn c++. Thanks a lot.
David on November 22, 2021 at 16:09
Thanks a lott !!
omar on December 08, 2021 at 18:08
Best explanation I found so far
thanks on December 09, 2021 at 20:00
This was very helpful. It felt like someone made this concept just to be mean. This made it... palatable.
Dat_$tix on December 27, 2021 at 19:51
Very cool explanation!! :D Thanks.
Issac on December 29, 2021 at 04:26
Thank you!
alison on January 04, 2022 at 22:30
great explanation!!
teonik on January 09, 2022 at 14:08
Great post! (Referring to GCC as "he" was a nice touch hehe)
EL jos on February 08, 2022 at 21:11
Une très bonne explication
Abhay on February 26, 2022 at 07:54
clear thoughts, very nice
TT on April 07, 2022 at 07:15
Well explained and good for C++ dummies
interestingLSY on April 13, 2022 at 14:27
WoW, Great Explanation!
Vicky Nguyen on May 23, 2022 at 19:23
Great explanation! It all makes sense now. Thank you!
Sky on May 29, 2022 at 05:39
Awesome, good explanation :)
Acnoo on June 06, 2022 at 16:03
Thank you for your excellent work! It helps a lot for me !
JS on June 11, 2022 at 12:12
Brilliantly articulated, thanks!
Elroy on June 19, 2022 at 14:26
Thank you so much.
Famous on June 30, 2022 at 14:52
This is sooooooo gooood!
Sajjad on July 25, 2022 at 20:31
Your explanation was so straightforward and understandable. Thank you so much :)
moona on July 28, 2022 at 12:01
thanks you! I'm new to cpp and your explanation really helps me a lot
Jimmy on July 29, 2022 at 15:05
Excellent and easy to understand explanation and example. Thank you!
ND on July 31, 2022 at 10:52
Best explanation of rvalue and lvalue that I have ever come across.You are an amazing writer!
Rudi on July 31, 2022 at 11:53
Thanks for the clear explanation. Really helped the concept click into place.
Isaac Ge on August 18, 2022 at 14:53
I comprehend the universe.
trungkientran on September 04, 2022 at 16:55
Great explanation. save me many hours
Kevin on September 29, 2022 at 22:57
Great explanation, helped me understand the concept. Thank you!