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 UA-cam 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 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.
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.
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;
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.
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.
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 :)
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/
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
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.
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.
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?
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
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?
+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
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
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++
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.
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.
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.
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.
best explanation on lvalue / rvalue ever!
💯% agreed
completely agreed.
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
By far the best explanation of lvalue and rvalue on UA-cam. 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.
u r genius.. Though the concept is simple it was really confusing to understand when you read other material. This video made life easy...
Wonderfully clearly and simply explained. This video is an asset to programmers _everywhere_. Thank you.
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.
Well explained, I was having trouble understanding this in my lectures. Thanks!
This is the simplest way of explaining what r-values and l-values are. Tysm
AWESOME 👍👍👍👍
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 UA-cam 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 =
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;
Hands down the best explanation of L-value and R-value, totally cleared my doubts
Glad we're covering this in the 4th week of my C++ class.
YT algorithm in 2019.. thank you for finding this for me.
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.
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.
Brilliant simplicity in explaining !! Love your precisely manner of presentation.
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.
Best/only explanation that I've been able to grasp. Thanks!
Mind Blown!! I definitely get what it is. I had such a hard time understanding the move operator. This made it easy.
Incredible explanation, thank you! Your videos are an incredible asset for anyone willing to dive into the deep with C/C++
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;
Very clear with great examples. Thank you!
awesome!
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.
I never really knew what a pointer is until now. You just explained pointers without talking about it.
Just amazing!
this is ingenious! superb explanation and I really like your simple style!
@11:23 the slide meant to say Misconception 3: rvalues are modifiable
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.
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 Sensei! This helped me understand rvalue and lvalue!
Awesome work! Thank you very much!
Great Lecture ❤
best c++ video
Thats good
Super. Thanks a lot Bo. I love your videos
hey bo, thanks for the time and effort you put into this. Saved my life.
Thanks a lot :) .. It's really nice and precise information about the concept...
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...
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 :)
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/
Thank you Bo, fantastic video
Absolute greate!
Seriously really really really really thank you 💝
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
Awesome video! Thanks Bo!
Really impressive, and good luck ;).
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.
These videos are so helpful! Thank you!
Thanks Bo that was super helpful, very appreciated!
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.
~38k+-1 million people knows about lvalue and rvalue including yourself, Bo Qian and Bjarne.Thank Qian and Bjarne
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?
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
Very helpful review. Thanks!
what about function? you can get the address of the function. is it rvalue or lvalue?
This was very helpful, thanks.
Just when I thought I understood it, I find out I don't. Still, learning is a process.
very nice. thank you.
Thank you, Bo Qian!
Thank you for the insight.
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?
why does dog() not have an identifiable memory address? it surely does ,and if i spat out the assembly i'd see it, no?
Thanks a lot. This video helped me a lot.
+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
Great,Thank you bro!
Good one thanks !
Thanks, how do you learn all these? Reading books?
Good
this is lovely
very informative ty
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
Thank you Sifu!
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++
nice
Is the concept of Lvalue and Rvalue in c and in c++ are same?
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.
Nice tutorial, ty
Thank you master
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.
can an array be a l-value or not
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?
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.
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
thanks for this.
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
Thanks a lot.
Thanks you so much
thanks a lot
You have to return value in your mind
A string constant has an identifiable memory address, though, and it is not a lvalue ;)
Thank you!
Make your Vim more visible and spread the word! :D
ok , but what is the point of doing foo()=50 ?!
int number1 = 2;
int number2 = 5;
change_the_big(big, little) = 1;
int& change_the_big(int& n1, int& n2){
return ( n1 > n2) ? &n1: &n2;
}
-------------------------------- result
number1 = 2
number2 = 1;
where are the note s