This was incredibly helpful and well-explained. It was like you answered every question I was going to have, and clarified anything that could have been confusing.
This video is quite nice actually. It explains where people might falter, just after reading a few lines, and gives counter examples to explain the point better. The video about move semantics is good as well.
There should be an option in RUclips to flag incorrect comments like this. What you've written sounds great...and maybe I'm wrong, if so, please post a link to direct me to a source for your comment. But l and r are closer to left and right, than what you wrote. The l and r derive from left and right hand sides of an assignment. Note, I used the word *derive*. It's more involved than just left and right, but that's where it comes from. msdn.microsoft.com/en-us/library/bkbs2cds.aspx
Notes from the video Every C++ expression yields either a R-value or an L-value. If the expression has an identifiable memory address, it’s L-value otherwise; it’s an R-value L-value Examples: int i; //i is a L-value int* p = &I; //i’s address is identifiable i = 2; //memory content is modified class dog; dog d1; // L-value of user defined type (class) // Most variables in c++ code are L-values //R-value Examples: int x = 2; // 2 is an R-value int x = i+2; // i+2 is an R-value; int* p = &(i+2);// error i+2 = 4; // error 2=i; Error Dog d1; d1 = dog(); // dog()is R-value of user defined type (class) int sum(int x, int y){return x+y;} int i = sum(3,4);// sum(3,4) is R-value const is an L-value and is not modifiable //R-values: 2,i+2,Dog(),sum(3,4),x+y //L-values: x, I, d1, p //Reference (or lvalue reference): int i; int& r=i; int& r =5; //error //Exception: Constant L-value reference can be assign an R-value; const int& r = 5; int square (int& x){return x*x;} square(i); //ok square(40); //error //Workaround: //////////////////////////////////////////////******** Remember ********//////////////////// int Square(cons tint& x ){return x*x;} // square(40) and square(I) work no errors this is really cool because it explains the need for the const keyword //L-value can be used to create an R-value int I =1; int x= i+2 int x =i; //R-value used to create a L-value int v[3]; *(v+2)=4; //Misconcetion 1 : function or operator always yields r values. int x = I +3; int y = sum(3,4); int myglobal; int&foo(){return myglobal;} foo() = 50; array[3]=50; //operator[] almost always generates l-value; //Misconception 2 : L-values are modifiable // c language: L-value means “value suitable for left-hand-side of assignment” // this definition is no longer true for C++ because L-value is not modifiable const int c = 1; // c is a L-value c=2; // error, c is not modifiable //misconception 3: R-values are not modifiable. i+3 = 6;//error sum(3,4)=7;//error //it is not true for user defined type (class) class dog; Dog().bark(); // bark() may change the state of the dog object;
Thank you for this explanation. Its important to understand these terms because I find they've really helped me out with debugging and understanding errors and warnings. When you understand the errors/warnings it can save you so much time.
Thank you a lot. Made things clearer. I was always confused about rvalues and lvalues. Now from what I've seen so far: lvalue = any object which location we can get in memory, rvalue = everything else.
The concepts of lvalue and rvalue were first introduced in C language, then C++ adopted the these until C++11 standard. These are now called value category. glvalue: lvalue + xvalue rvalue: prvalue + xvalue The C++ language is evolving rapidly these years. So, new concepts are introduced with new standards, and some features become deprecated. glvalue, lvalue, prvalue, xvalue... constexpr, constexpr ... etc. become crystal-clear, once you understand Assembler language. In fact, these terms are not necessary at all if you understand Assembler. All these strange terms are introduced to help those people understand lower-level CPU operations in C++ programmer s perspective. All of those advanced concepts of C++ can never be fully understood without some level of Assembler language experience.
Generally, rvalues are values whose address cannot be obtained by dereferencing them, either because they are literals or because they are temporary in nature (such as values returned by functions or explicit constructor calls). Taken from www.cplusplus.com/reference/utility/move/
They were defined this way because they were looking at the left side of and Equal and the Right side of the equals. Thus lvalue and rvalue. But rvalue are in expressions and other places.
WOW.. Thanks bro. Im really confuse about the lvalue and rvalue thingy. How about explaining the concepts of constant? i believe constants are a major factor in c++
If you create a custom class that is similar to a sequence container, one thing you can implement in your class is an overloaded subscript operator that returns a rvalue reference to the sequence at specific subscript index so that you can modify the value at that index of the sequence. For example, suppose you create a class called ExamScores that stores a list of exam scores using a member variable that is an private int pointer called m_ptr. Furthermore, suppose you want to treat an object of class ExamScores as if it were an array instead of having to call a setter function like: void setScoreAtIndex(int index, int value) { m_ptr[index] = value; } Then your class would need an overloaded subscript function like this (note this example disregards invalid index): int& ExamScores::operator[](int index) { return m_ptr[index]; } The overloaded function will allow you to treat an object of class ExamScores as if it were an array: int size = 3; ExamScores scores{size}; scores[0] = 92; scores[1] = 75; scores[2] = 88;
Thank you for this explanation, i would like to ask you a question . Is it possible to cast a lvalue ? Ex : I declare a variable i as integer and at certain point in my code i want i to be char . Is it possible to do that casting on lvalues ? Thank you
At 8:10 when you're talking about x = i; and asked if i is an lvalue or an rvalue. I understand the implicit conversion as we're making a copy of i and storing it in x, therefore x is the lvalue and i is an implicit rvalue, but if we did x = &i; would both x and i be an lvalue, as we're setting x to its address? Or would i still be the rvalue? Thanks :)
02:44 I don't think that modifyability matters here at all. `i` can be defined `const`, making it impossible to modify, but it won't change its lvalue status, because it technically still does have an address and it is referred to by a name in our code. 03:30 I think that you're putting the cart before the horse right here: The fact that you can apply an `&` operator to it, doesnt necessarily mean that it is an L-value. It's the other way around: WHEN something already IS an R-value, THEN you can apply `&` to it, or assign to it. But you have to find out FIRST if a certain expression is an L-value, using the _actual_ language rules about R/L-values. 03:44 Well, here we have a built-in type (an integer), and a numeric literal. But what if `i` was an object of some user-defined type that has an overloaded `operator+` that returns a non-const temporary? Technically, we can still assign a new value to it, right? Otherwise, things like this wouldn't be possible: std::complex a{2,3}; std::complex b = (a*3) += 5; std::cout
There is a difference between actually taking the address of a variable (with the address-of operator, &) and simply assigning an arbitrary value to a pointer variable. You are doing the latter, which not only is not an rvalue, it's also almost definitely going to give you an access violation if you try to dereference that pointer.
For people coming from other (OOP) languages, the question remains: so what? Why do we care about rvalue and lvalue? Some illuminating examples can be greatly helpful.
if 50 is an rvalue, you explained that the only way that an lvalue reference can be assigned by an rvalue is if that lvalue reference was declared constant, but your function foo() doesn't have const int& declared as the return type it's just int&. How can I assign a non-constant lvalue reference to an rvalue??? seems contradicting?
y is an lvalue I think. You can assign something to y (even if it's a bit pointless because it's passed by value, but you still can) , so by my understanding it must be an lvalue.
Please, if u can explain the c++11 with gdb debugger using unix OS.Furthermore, To be specific i need these things to be explained. If u have time,,,,,Compilation • Use g++11 to compile with C++ 2011 standard. • Use w++11to in addition include all warnings commonly good. • Useg++11filterto in addition filter the errors through gccfilter .• Use w++11 filter to use both warnings andgccfilter .• Usebcheck ./a.out to check for memory leaks when you run your program. A short and simple program will work for me.
I believe you have forgotten to add "sum" (that is, the function itself) to the lvalue list. Am I wrong? While the function call sum(3,4), that is, the result of its call, is a rvalue, I think the function itself (function pointer) is a lvalue.
A function pointer is lvalue. However, a function call, more specifically what it returns, like sum(3, 4) may be either lvalue or rvalue depending on the return type int& or int. When you call a function you deference the function pointer. The name of the function itself is the function pointer. cout
In misconception 1: is not foo returning a lvalue reference of lvalue myglobal ? Assigning 50 to lvalue reference should generate error unless we use const? But it compiles fine. Can someone help me understand this?
+Moshe Rabaev . couse function foo() does not return a non initialized int&, Its returning a reference to the global variable "myglobal" , myglobal can be assigned with rvalue 50
In the last example "dog" suddenly became an rvalue, while it should be lvalue as it has to be defined like "Dog dog;" where Dog is a class. Even though dog is modifiable if some method changes it's state, it's still and lvalue, not an rvalue.
yes, dog() create a temporary object, but this temporary object doesn't have a IDENTIFIABLE memory address, because it doesn't have a name attach to it, right ? So you can't identify it's address, then it is a rvalue
Ten years later and this channel still best channel explaining modern c++ in a concise and informative way.
Probably the best explanation of l/r-values I have seen.
really clear my doubts i have been a c++ programmer for 7+ years of experience but really u cleared my doubt now
That's, honestly, either a lie, or just plain sad and weird.
@@VivekYadav-ds8oz no
best explanation on lvalue / rvalue ever!
💯% agreed
completely agreed.
By far the best explanation of lvalue and rvalue on RUclips. Thanks Bo!
This was incredibly helpful and well-explained. It was like you answered every question I was going to have, and clarified anything that could have been confusing.
This is the simplest way of explaining what r-values and l-values are. Tysm
Wonderfully clearly and simply explained. This video is an asset to programmers _everywhere_. Thank you.
u r genius.. Though the concept is simple it was really confusing to understand when you read other material. This video made life easy...
Bo, your videos are concise, clear and very useful! Thanks for the hard work.
This video is quite nice actually. It explains where people might falter, just after reading a few lines, and gives counter examples to explain the point better.
The video about move semantics is good as well.
lvalue = logical address value , rvalue = register value
this comment helped me more than the vid thanks
How about lvalues as "Location (memory)" values? Better than "logical address".
Actually, according to the video that would be wrong, since rvalue is a definition by exclusion. An r value is what an lvalue isn't
There should be an option in RUclips to flag incorrect comments like this. What you've written sounds great...and maybe I'm wrong, if so, please post a link to direct me to a source for your comment. But l and r are closer to left and right, than what you wrote. The l and r derive from left and right hand sides of an assignment. Note, I used the word *derive*. It's more involved than just left and right, but that's where it comes from. msdn.microsoft.com/en-us/library/bkbs2cds.aspx
l and r is for left and right. lvalue means something to be the left side operand of assignment operator =
I never really knew what a pointer is until now. You just explained pointers without talking about it.
Hands down the best explanation of L-value and R-value, totally cleared my doubts
Well explained, I was having trouble understanding this in my lectures. Thanks!
AWESOME 👍👍👍👍
very interesting. rvalues are things i had alot of questions about when learning c++, without knowing there was a term for them
I marvel at the intelligence of Bo Qian. He is the most amazing teacher of anything I've found on the Internet.
Notes from the video
Every C++ expression yields either a R-value or an L-value.
If the expression has an identifiable memory address, it’s L-value otherwise; it’s an R-value
L-value Examples:
int i; //i is a L-value
int* p = &I; //i’s address is identifiable
i = 2; //memory content is modified
class dog;
dog d1; // L-value of user defined type (class)
// Most variables in c++ code are L-values
//R-value Examples:
int x = 2; // 2 is an R-value
int x = i+2; // i+2 is an R-value;
int* p = &(i+2);// error
i+2 = 4; // error
2=i; Error
Dog d1;
d1 = dog(); // dog()is R-value of user defined type (class)
int sum(int x, int y){return x+y;}
int i = sum(3,4);// sum(3,4) is R-value
const is an L-value and is not modifiable
//R-values: 2,i+2,Dog(),sum(3,4),x+y
//L-values: x, I, d1, p
//Reference (or lvalue reference):
int i;
int& r=i;
int& r =5; //error
//Exception: Constant L-value reference can be assign an R-value;
const int& r = 5;
int square (int& x){return x*x;}
square(i); //ok
square(40); //error
//Workaround:
//////////////////////////////////////////////******** Remember ********////////////////////
int Square(cons tint& x ){return x*x;} // square(40) and square(I) work no errors this is really cool because it explains the need for the const keyword
//L-value can be used to create an R-value
int I =1;
int x= i+2
int x =i;
//R-value used to create a L-value
int v[3];
*(v+2)=4;
//Misconcetion 1 : function or operator always yields r values.
int x = I +3;
int y = sum(3,4);
int myglobal;
int&foo(){return myglobal;}
foo() = 50;
array[3]=50; //operator[] almost always generates l-value;
//Misconception 2 : L-values are modifiable
// c language: L-value means “value suitable for left-hand-side of assignment”
// this definition is no longer true for C++ because L-value is not modifiable
const int c = 1; // c is a L-value
c=2; // error, c is not modifiable
//misconception 3: R-values are not modifiable.
i+3 = 6;//error
sum(3,4)=7;//error
//it is not true for user defined type (class)
class dog;
Dog().bark(); // bark() may change the state of the dog object;
Glad we're covering this in the 4th week of my C++ class.
Thank you for this explanation. Its important to understand these terms because I find they've really helped me out with debugging and understanding errors and warnings. When you understand the errors/warnings it can save you so much time.
Thank you a lot. Made things clearer. I was always confused about rvalues and lvalues. Now from what I've seen so far: lvalue = any object which location we can get in memory, rvalue = everything else.
YT algorithm in 2019.. thank you for finding this for me.
Brilliant simplicity in explaining !! Love your precisely manner of presentation.
Mind Blown!! I definitely get what it is. I had such a hard time understanding the move operator. This made it easy.
awesome!
Best/only explanation that I've been able to grasp. Thanks!
Thank you very much. Thanks to you, I don't have the brain ache over pages of C++ book that doesn't make much sense.
Incredible explanation, thank you! Your videos are an incredible asset for anyone willing to dive into the deep with C/C++
Thats good
this is ingenious! superb explanation and I really like your simple style!
best c++ video
Finally I understand the concept, I do not know why my c++ book does not define it as you have, lvalues have a identifiable memory address...
Very clear with great examples. Thank you!
The concepts of lvalue and rvalue were first introduced in C language, then C++ adopted the these until C++11 standard. These are now called value category.
glvalue: lvalue + xvalue
rvalue: prvalue + xvalue
The C++ language is evolving rapidly these years. So, new concepts are introduced with new standards, and some features become deprecated.
glvalue, lvalue, prvalue, xvalue... constexpr, constexpr ... etc. become crystal-clear, once you understand Assembler language. In fact, these terms are not necessary at all if you understand Assembler. All these strange terms are introduced to help those people understand lower-level CPU operations in C++ programmer s perspective.
All of those advanced concepts of C++ can never be fully understood without some level of Assembler language experience.
~38k+-1 million people knows about lvalue and rvalue including yourself, Bo Qian and Bjarne.Thank Qian and Bjarne
Great Lecture ❤
Just amazing!
Thanks Sensei! This helped me understand rvalue and lvalue!
Seriously really really really really thank you 💝
Thanks a lot :) .. It's really nice and precise information about the concept...
hey bo, thanks for the time and effort you put into this. Saved my life.
Awesome work! Thank you very much!
Super. Thanks a lot Bo. I love your videos
Generally, rvalues are values whose address cannot be obtained by dereferencing them, either because they are literals or because they are temporary in nature (such as values returned by functions or explicit constructor calls).
Taken from www.cplusplus.com/reference/utility/move/
Just when I thought I understood it, I find out I don't. Still, learning is a process.
Thank you Bo, fantastic video
They were defined this way because they were looking at the left side of and Equal and the Right side of the equals. Thus lvalue and rvalue. But rvalue are in expressions and other places.
Really impressive, and good luck ;).
very nice. thank you.
Awesome video! Thanks Bo!
These videos are so helpful! Thank you!
Thanks a lot. This video helped me a lot.
This was very helpful, thanks.
Very helpful review. Thanks!
Absolute greate!
Good
WOW.. Thanks bro. Im really confuse about the lvalue and rvalue thingy. How about explaining the concepts of constant? i believe constants are a major factor in c++
very informative ty
Good one thanks !
Thank you for the insight.
this is lovely
Thanks Bo that was super helpful, very appreciated!
Thank you, Bo Qian!
Thank you master
9:45 me : "...this is a weird looking code . I never write code like this." Bo Qian: "what abt array[3] = 50?" me: speechless...
If you create a custom class that is similar to a sequence container, one thing you can implement in your class is an overloaded subscript operator that returns a rvalue reference to the sequence at specific subscript index so that you can modify the value at that index of the sequence. For example, suppose you create a class called ExamScores that stores a list of exam scores using a member variable that is an private int pointer called m_ptr. Furthermore, suppose you want to treat an object of class ExamScores as if it were an array instead of having to call a setter function like:
void setScoreAtIndex(int index, int value) {
m_ptr[index] = value;
}
Then your class would need an overloaded subscript function like this (note this example disregards invalid index):
int& ExamScores::operator[](int index) {
return m_ptr[index];
}
The overloaded function will allow you to treat an object of class ExamScores as if it were an array:
int size = 3;
ExamScores scores{size};
scores[0] = 92;
scores[1] = 75;
scores[2] = 88;
what about function? you can get the address of the function. is it rvalue or lvalue?
nice
Thank you for this explanation, i would like to ask you a question .
Is it possible to cast a lvalue ?
Ex :
I declare a variable i as integer and at certain point in my code i want i to be char . Is it possible to do that casting on lvalues ?
Thank you
At 8:10 when you're talking about x = i; and asked if i is an lvalue or an rvalue. I understand the implicit conversion as we're making a copy of i and storing it in x, therefore x is the lvalue and i is an implicit rvalue, but if we did x = &i; would both x and i be an lvalue, as we're setting x to its address? Or would i still be the rvalue? Thanks :)
Nice tutorial, ty
Thank you Sifu!
Great,Thank you bro!
02:44 I don't think that modifyability matters here at all. `i` can be defined `const`, making it impossible to modify, but it won't change its lvalue status, because it technically still does have an address and it is referred to by a name in our code.
03:30 I think that you're putting the cart before the horse right here: The fact that you can apply an `&` operator to it, doesnt necessarily mean that it is an L-value. It's the other way around: WHEN something already IS an R-value, THEN you can apply `&` to it, or assign to it. But you have to find out FIRST if a certain expression is an L-value, using the _actual_ language rules about R/L-values.
03:44 Well, here we have a built-in type (an integer), and a numeric literal. But what if `i` was an object of some user-defined type that has an overloaded `operator+` that returns a non-const temporary? Technically, we can still assign a new value to it, right? Otherwise, things like this wouldn't be possible:
std::complex a{2,3};
std::complex b = (a*3) += 5;
std::cout
Hello Bo Quian , AT 8:20 ...How (V+2) become R Value...if it is having an Identifiable address...hence i can do int *ptr = V + 2;
There is a difference between actually taking the address of a variable (with the address-of operator, &) and simply assigning an arbitrary value to a pointer variable. You are doing the latter, which not only is not an rvalue, it's also almost definitely going to give you an access violation if you try to dereference that pointer.
this is pointer arithmetic *(v+k) is just v[k] which is clearly an identifiable address on the heap
thanks for this.
Thanks a lot.
For people coming from other (OOP) languages, the question remains: so what? Why do we care about rvalue and lvalue? Some illuminating examples can be greatly helpful.
move semantics
@11:23 the slide meant to say Misconception 3: rvalues are modifiable
Thanks you so much
Thanks, how do you learn all these? Reading books?
if 50 is an rvalue, you explained that the only way that an lvalue reference can be assigned by an rvalue is if that lvalue reference was declared constant, but your function foo() doesn't have const int& declared as the return type it's just int&. How can I assign a non-constant lvalue reference to an rvalue??? seems contradicting?
at 4:56 you forgot to type in "y" which is an rvalue too, correct?
y is an lvalue I think. You can assign something to y (even if it's a bit pointless because it's passed by value, but you still can) , so by my understanding it must be an lvalue.
thanks a lot
Please, if u can explain the c++11 with gdb debugger using unix OS.Furthermore, To be specific i need these things to be explained. If u have time,,,,,Compilation
• Use g++11 to compile with C++ 2011 standard.
• Use w++11to in addition include all warnings commonly good.
• Useg++11filterto in addition filter the errors through gccfilter
.• Use w++11 filter to use both warnings andgccfilter
.• Usebcheck ./a.out to check for memory leaks when you run your program.
A short and simple program will work for me.
You have to return value in your mind
I believe you have forgotten to add "sum" (that is, the function itself) to the lvalue list. Am I wrong? While the function call sum(3,4), that is, the result of its call, is a rvalue, I think the function itself (function pointer) is a lvalue.
Thank you!
Is the concept of Lvalue and Rvalue in c and in c++ are same?
Well, if I know right, you can have a pointer point to a function. Doesn't that make functions lvalues?
They have a address in the memory, don't they?
A function pointer is lvalue. However, a function call, more specifically what it returns, like sum(3, 4) may be either lvalue or rvalue depending on the return type int& or int. When you call a function you deference the function pointer. The name of the function itself is the function pointer. cout
why does dog() not have an identifiable memory address? it surely does ,and if i spat out the assembly i'd see it, no?
In misconception 1: is not foo returning a lvalue reference of lvalue myglobal ? Assigning 50 to lvalue reference should generate error unless we use const? But it compiles fine. Can someone help me understand this?
+Moshe Rabaev . couse function foo() does not return a non initialized int&, Its returning a reference to the global variable "myglobal" , myglobal can be assigned with rvalue 50
Make your Vim more visible and spread the word! :D
can an array be a l-value or not
I don't understand in the part int i=4; int x=i why i is rvalue?i has its own address to store 4.
For Lvalue, when you say memory do you mean the RAM or ROM?
RAM. ROM is only used to help the system boot into an OS. It has nothing to do with this.
+LapsedUnity what about const variables?
In the last example "dog" suddenly became an rvalue, while it should be lvalue as it has to be defined like "Dog dog;" where Dog is a class.
Even though dog is modifiable if some method changes it's state, it's still and lvalue, not an rvalue.
A string constant has an identifiable memory address, though, and it is not a lvalue ;)
Why is constructor dog() an rvalue, it returns an address right?
Thanks Peterolen
isn't it called xvalue ?
yes, dog() create a temporary object, but this temporary object doesn't have a IDENTIFIABLE memory address, because it doesn't have a name attach to it, right ? So you can't identify it's address, then it is a rvalue
lvalue ^^
int& back(int& i) { return i; }
int i = 5;
bacK(i) = 6;
printf(i); // will show "6"