Post 1 - References
1.1 - Lvalue references and const lvalue references
1.2 - Rvalue references
1.3-Move semantics
" A reference is an alternative name for an object, an alias. The main use of references is for specifying arguments and return values for functions in general and for overloaded operators in particular."
1.1 - Lvalue references and const Lvalue references
-Lvalue reference: (T& ref) where T is any type- ref is a reference to an object of type T
T& ref define a non constant reference to an object with the name ref. We can take the adress of the object or write to it. They can be in the left side of a assignment or expression. They can be arguments of functions. They are, also, used as return types in functions. A reference is like a (constant) pointer that is dereferenced each time it is used. We can think this way and dont forget they are diferent from pointers. We have to initialize a lvalue reference with some object.
Ex:
int* ptr; // pointer to a int. A pointer can be declared without initialization
int& var; //error. No value to initialize. lvalue references need initialization.
ptr=&var; // pointer p point the same object that var refer to: a int with value 1 .(*ptr) is 1
int& r{var}; //r initialized with var. Both references refer the same object, an int with value 1
int& var=1 ; // error. cannot initialize a reference with a rvalue(temporary, no name initializer )
The functions returning a reference can be used in left hand and rigth hand of assignment expressions.
Ex:
int& Func2(int& x){return x;} //return reference
int x =10;
int res = Func2(x); //Function2 in rigth side of assignement res=10
Func2(res)=99; // Function2 in left side of assignment (lvalue) res = 99
- Const lvalue references : (const T& ref)where T is any type- ref is a reference to an object of type T
A const lvalue reference refers to a constant, which is immutable from the point of view ofthe user of the reference.
This kind of references are useful objects when passing parameters to functions .
Ex:
int x = 10;
int y = 20;
int& z = x+y //error. cannot bind non-const lvalue reference of type ‘int&’ to an rvalue
int& var=1 ; // error. cannot initialize a reference with a rvalue(temporary, no name initializer )
const double& var=1; // ok
const int& z = x+y // ok
const double& var3{1} // ok. With a const reference we can use a temporary to initialization.
1. (implicit type conversion if necessary) int to double
2. a temporary object is created with value 1(temporary variable)
3. The temporary variable, with value one, is used to initialize the reference var3
Run and play with code: http://tpcg.io/kNEXV8yx
1.2 - Rvalue references
-Rvalue references: A rvalue reference named ref is declared like this: (T&& ref) where T is any typeThe '&&' is the token which identifies the reference as an "rvalue reference" (bindable to an rvalue) and distinguishes it from our current reference syntax.An rvalue reference refers to a temporary object, which the user of the reference can (and typically will) modify, assuming that the object will never be used again. An rvalue reference can bind to an rvalue, but not to an lvalue. In that, an rvalue reference is exactly opposite to an lvalue reference.
For example :
int x = 10;
int y = 20;
const int& u=1;
const int& cref = x + y; // const ref can attach to r-value
//int & Lref = x + y; // illegal -- Lvalue reference cannot bind rvalue
int && r2 = x + y; //Ok Rvalue can attach to Rvalue reference
int && r4=10; // ok " " "
//int && r3=x; //cannot bind rvalue reference of type ‘int&&’ to lvalue of type ‘int’
r4=static_cast<int&&>(y); //ok we can use with same result r4=std::move(r);
int array[10];
int&& arvalue=4;// named Rvalue reference is like a lvalue reference
If you define only Func(const int& x) it can be called on l-values and r-values, but it is not possible to make it distinguish between l-values and r-values. That is possible only by implementing Func(int&& x). With the two versions of Func:
Func(int& x) and Func(int&& x);
the compiler can choose what version to use on rvalues and lvalues. That is importante to implement de move constructor and assign move operators. We will see what is move semantic later.
for example. Run and play Code: http://tpcg.io/hsc0hCjv
Func(x);
//call Func(const int& x) parameter is a lvalue
Func(array[4]); //call Func(const int& x) parameter is a lvalue
Func(x + y); //call Func(int&& x) temporary(x+y)-> parameter is a rvalue
Func(100); //call Func(int&& x) parameter is a rvalue
Func(std::move(x)); //call Func(int&& x) parameter is a rvalue reference casting x to
rvalue
Func(Func3(x)); //call Func(int&& x) parameter is a rvalue returned by Func3
Func(arvalue); //call Func(const int& x) arvalue is a named Rvalue reference