lvalue vs rvalue Reference CS 247 Module 4

  • Slides: 9
Download presentation
lvalue vs. rvalue Reference CS 247 Module 4 Supplement Scott Chen

lvalue vs. rvalue Reference CS 247 Module 4 Supplement Scott Chen

How to use this guide? Ø Understand what lvalue and rvalue are • Slide

How to use this guide? Ø Understand what lvalue and rvalue are • Slide 3 and 4 Ø Understand what lvalue reference and rvalue reference are • Slide 5, 6, and 7 Ø Understand the difference among 1) Pass by Value, 2) Pass by lvalue Reference, 3) Pass by constant lvalue Reference, and 4) Pass by rvalue Reference. • Slide 8 and 9

Definition of lvalue vs. rvalue Ø Traditionally, concepts existing before C++11: • lvalue –

Definition of lvalue vs. rvalue Ø Traditionally, concepts existing before C++11: • lvalue – a value that “formally” occupies memory resource for extended use § Physically stored in the memory § Program sector § Heap sector § Explicitly-named local variables on stack § Data-Address Duality properly apples (can reference and dereference them normally) § int i = 3; // i is an lvalue, but 3 is not; § int *j = &i; // permitted. i is lvalue, so it’s fine for us to obtain its reference (address) § int& foo(); // an implicit integer memory slot will be formally allocated for return int* j = &foo(); // foo() is an lvalue (memory address of the return int memory slot) § foo() = 777; // permitted, because foo() is an lvalue // (although pointless) this statement sets the value of the return int in memory

Definition of lvalue vs. rvalue Ø Traditionally (before C++11) • rvalue – a value

Definition of lvalue vs. rvalue Ø Traditionally (before C++11) • rvalue – a value that “informally” occupies memory resource for temporary use § Implicit values on stack (like return values of a function that will be popped automatically) § Arbitrary constants (hard-coded values in the machine code) § All rvalues will be released soon, often within one statement • Data-Address Duality does not apply normally § int foobar(); // int return through stack. (no memory is explicitly allocated for return value) int m = foobar(); // foobar() is considered an rvalue (or its returned value is an rvalue) § int *n = &foobar(); § int k = 777; // // // NOT PERMITTED, because foobar() is returning an rvalue // C++ hides away the implicit stack-passing operations, not allowing access to // these temporary values normally. 777 is an rvalue – arbitrary constant in machine code These constants are loaded from memory as physical numbers in CPU register for the operation in this statement ONLY, so we cannot refer to it with any memory address (CPU registers are not touchable through C++ code explicitly)

Pass by Reference Ø Traditionally (before C++11) • Only lvalues are permitted to be

Pass by Reference Ø Traditionally (before C++11) • Only lvalues are permitted to be passed by reference § void foo 2(int &myint); //Pass by Reference § int m = 3; foo 2(m); //Permitted, because m has a physically memory address to refer to • rvalues are strictly not allowed to be passed by reference. Pass by value ONLY. § foo 2(777); //NOT PERMITTED, because 777 has no physical memory address to refer to § void foobar 2(int myint 2); //Pass by value foobar 2(777); // Permitted

Pass by Reference Ø Traditionally (before C++11) • Only lvalues are permitted to by

Pass by Reference Ø Traditionally (before C++11) • Only lvalues are permitted to by passed by reference • rvalues are strictly not allowed to be passed by reference. Pass by value ONLY. • Is there any problem here? § Not really, in most of the case scenarios • Except when you start applying std: : move() § Move() assumes that the source is not to be preserved after move operations; therefore, the source to be moved by move() can either be lvalue (persistent) or rvalue (temporary) § For better efficiency, move() also should use pass-by-reference whenever possible (particularly for large data size) § However, C++ (back in ver. 11) does not permit rvalue to be passed by reference § Thus, move() had the following restrictions earlier than C++11 § If source is lvalue, pass by reference § If source is rvalue, pass by value (copy) performance hit with large data size!!

Pass by Reference Ø After C++11 • move() performance issue is addressed by permitting

Pass by Reference Ø After C++11 • move() performance issue is addressed by permitting special access to “rvalue reference” • rvalue reference - Allowing temporary access to the memory location of an rvalue § Exception – still no access to rvalues on CPU registers (because they have no memory address at all) • Then, move() can always accept pass-by-reference, but using rvalue reference § If source is lvalue, nothing changes – it’s still pass-by-reference § If source is rvalue, pass by rvalue-reference – it’s ALSO pass-by-reference, no performance compromise anymore! • Thus, the traditional variable reference now got split into two versions: § lvalue reference (&) – reference (memory address) of an lvalue § rvalue reference (&&) – reference (temporary memory address) of an rvalue

Understand of Different Param Passing Ø Pass by Value • “I know you love

Understand of Different Param Passing Ø Pass by Value • “I know you love my sports car, but it’s too precious for me to lend it to you. So, here is an identical sports car I’ve bought on Auto. Trader. com (yup I’m a big shot); just take it and play with it. ” • int Pb. V_example(Car my. Car); § // my. Car ADT instance is copied and passed into the function (operation-expensive) § // Whatever you do on this copy of my. Car will not affect the source Ø Pass by Reference (lvalue reference) • “You love my sports car, eh? Well, we are good buddies, so I will lend it to you. I trust that you can take care of it well; even if it comes back slightly different, I’m sure you will keep it in good shape. ” • int Pb. R_example(Car &my. Car); § // The reference (memory address) of my. Car ADT instance is passed in to the function § // Whatever you do on this copy of my. Car WILL modify the original source

Understand of Different Param Passing Ø Pass by Constant Reference (const lvalue reference) •

Understand of Different Param Passing Ø Pass by Constant Reference (const lvalue reference) • “You said you love my sports car? Sure, I can give you a tour; you can take a good look at it in my garage, but don’t touch it – you won’t be able to afford the repairs. Just looking, no touching!” • int Pbc. R_example(const Car &my. Car); § // The constant reference (memory address) of my. Car ADT instance is passed in to the function § // The source ADT remains read-only – you are not permitted to change the contents of my. Car ADT Ø Pass by rvalue Reference • “You said you love my sports car? Well you know what, I wanted to get rid of it to get a new one anyways. Just take it, it’s yours now. Whether you cherish or trash it, it’s none of my business anymore. ” • int Pbr. R_example(Car &&my. Car); § // The rvalue reference (memory address) of my. Car ADT instance is passed in to the function, indicating that my. Car “can potentially be” a rvalue, and can be tampered with no consequences. § // Do anything you want with my. Car ADT instance through rvalue reference – even if you trash it. It’s fine, because it should be destroyed automatically when we are done with it.