fbpx

You’ll sometimes come across lvalues and rvalues maybe when trying to understand compiler error messages or when reading docs. A basic understanding will go a long way to making sense of them.

The names look strange, lvalue and rvalue. They started out, as I always understood them, to identify what things could go on the left side of an assignment and what things could go on the right side. If you declare an int variable called height and later assign it the value 2, then your code will say height is assigned 2. In this example, height appears to the left of the assignment operator and the number 2 integer literal is on the right. So height is an lvalue and 2 is an rvalue.

It turns out that there are actually two main properties that are important for variables and even other expression types. Does it have an identity? And is it moveable? What do these mean?

Anytime you have two properties, you’ll have four possible ways they can be combined. One of the combinations in this case is just not needed though. That combination is whenever an object has no identity and cannot be moved. The language designers felt that this combination serves no purpose. So it’s gone.

That leaves the following three combinations:

  • If it’s identifiable and not moveable, then this is the traditional, in-depth meaning of an lvalue.
  • If it’s not identifiable but is moveable, then this is what’s called a pure rvalue. Or a prvalue.
  • If it’s both identifiable and moveable, then all I can say here is you need to be careful. This is called an xvalue. And the language designers left the meaning of the letter x unspecified. Think of it as an expert value. If you’re dealing with xvalues, then you need to know what you’re doing.

What happened to rvalues? Well, rvalues are now defined to be more of a property. Rvalues map to the moveable property and include both xvalues and prvalues.

And the other property, identifiable, is now called general lvalues or glvalues and includes both lvalues and xvalues.

Listen to the full episode or read the full transcript below for more.

Transcript

You’ll sometimes come across lvalues and rvalues maybe when trying to understand compiler error messages or when reading docs. A basic understanding will go a long way to making sense of them.

The names look strange, lvalue and rvalue. They started out, as I always understood them, to identify what things could go on the left side of an assignment and what things could go on the right side.

If you declare an int variable called height and later assign it the value 2, then your code will say height is assigned 2. Notice I try to avoid saying height equals 2. Because that can get confused with an equality test to see if the current value of height is 2 or not. It’s a good habit for you to follow.

In this example, height appears to the left of the assignment operator and the number 2 integer literal is on the right. So height is an lvalue and 2 is an rvalue.

You can’t reverse these and try to say that the number 2 is assigned height. That doesn’t make any sense. And if you try to do something like this, your compiler is likely to give you an error message about how the number 2 cannot be an lvalue.

Things get a little more complicated so don’t worry if the rest of this episode doesn’t make sense. You’ve already got the major understanding just knowing that some things can be assigned new values and some things can’t.

In case you thing that any simple int variable is automatically an lvalue, well that’s not always the case. Some languages like C++ allow you to declare variables to be const. Then they can’t be changed.

While researching this episode, I found reference to another possible meaning of lvalue and rvalue. I don’t know if this is correct but it does make sense and I hope will give you another way to think about this topic. Back in the days before C++ and likely before C when the only language available was assembly, a variable was really just an address in memory. And since memory has a series of addresses or locations, the name lvalue came about to mean the location value. Now, it’s often useful to be able to move the contents of a memory address or location into one of the processors internal registers so the value can be manipulated. And because we’re not talking about a location in memory anymore but a value stored in a register, it became known as an rvalue which stands for register value.

Like I said, this is a story I came across that seems to fit well. At least it makes sense for programming in assembly. I’ll explain more about lvalues and rvalues right after this message from our sponsor.

I’ll have to do more research to see how much of what I’m about to explain applies to C#. Remember back in some of the very first episodes when I said this programming profession is a lifelong commitment to learning? This is a good example where I’m still learning. This is the type of understanding that can also elevate you way above your peers. Even other programmers with years of experience. You just don’t often need to understand this and when you do, a lot of developers give up instead of digging a little deeper.

It turns out that there are actually two main properties that are important for variables and even other expression types. Does it have an identity? And is it moveable? What do these mean?

Well, an identity is anytime your application can refer to something by name, or through a pointer, or through a reference. If you can tell if something is different from something else or if it’s been changed in some way, then it has an identity.

Moveable is a bit harder to understand. Let’s say you have two integer variables, height and width, and you write in your code that height is assigned width. This means that after the assignment both height and width will have the same value and that value will be whatever the width was before the assignment.

There’s another form of assignment though that can look just like this and that’s when the width gets moved into the height. When this happens, then height will be updated to contain the original value of the width and the width will be left in a valid but unspecified state. Wow! That’s the part where most people get lost. If you need to rewind and listen again, go ahead. It’s important.

Like most of my examples, I like to start out simple. Unfortunately, in this case the simple example can leave you wondering why? Why would the possibility that an int can be left in a valid but unspecified state even exist in the language. It didn’t always exist. This is sort of new. It makes more sense for a collection. Let’s say that you have a large collection of millions of ints that you need to transfer to another collection. You could do the traditional assignment where each int needs to get copied over to the new collection. That can take a lot of time. And if you never need to refer to the original collection ever again, then it’s a complete waste. What if you could just move the contents? You could then leave the original collection in an empty state which is perfectly valid. The language doesn’t tell you what to do with the original object so that’s why it’s unspecified. All the language says is that whatever you do, just make sure it’s valid. This is moveable.

Okay, back to the properties identifiable and moveable. Anytime you have two properties, you’ll have four possible ways they can be combined. One of the combinations in this case is just not needed though. That combination is whenever an object has no identity and cannot be moved. The language designers felt that this combination serves no purpose. So it’s gone.

That leaves the following three combinations:

◦ If it’s identifiable and not moveable, then this is the traditional, in-depth meaning of an lvalue.
◦ If it’s not identifiable but is moveable, then this is what’s called a pure rvalue. Or a prvalue.
◦ If it’s both identifiable and moveable, then all I can say here is you need to be careful. This is called an xvalue. And the language designers left the meaning of the letter x unspecified. Think of it as an expert value. If you’re dealing with xvalues, then you need to know what you’re doing.

What happened to rvalues? Well, rvalues are now defined to be more of a property. Rvalues map to the moveable property and include both xvalues and prvalues.

And the other property, identifiable, is now called general lvalues or glvalues and include both lvalues and xvalues.

I’ll pick up this topic again in a future episode when I explain how to move objects instead of just copying them.