[C ++ 11] _ [primary] _ [left reference declaration and right reference Declaration]
Scenario: You can see the right value reference in the remove_reference struct &. What is the use of the right value reference here? We often find that int & and int & are similar application types. The first is the left value reference declaration, and the second is the right value reference declaration. cppreference, which is directly referenced in the following example, has been completely written and there is no need to write it again. syntax
Declaration of reference to the left value: & attr (optional) declarator (1)
Right Value reference Declaration: & attr (optional) declarator (2) (since C ++ 11)
Declaration of left Reference &
-1. The left value reference can be understood as the object alias. The left value reference must be initialized and cannot be re-assigned.
#include
#include
int main(){ std::string s = "Ex"; std::string& r1 = s; const std::string& r2 = s; r1 += "ample"; // modifies s// r2 += "!"; // error: cannot modify through reference to const std::cout << r2 << '\n'; // prints s, which now holds "Example"}
-2. When calling a function, it can be used as a reference parameter.
#include
#include
void double_string(std::string& s){ s += s; // 's' is the same object as main()'s 'str'}int main(){ std::string str = "Test"; double_string(str); std::cout << str << '\n';}
-3. When the return value of a function is the left value, the expression called by this function can be considered as a left value expression.
#include
#include
char& char_number(std::string& s, std::size_t n){ return s.at(n); // string::at() returns a reference to char}int main(){ std::string str = "Test"; char_number(str, 1) = 'a'; // the function call is lvalue, can be assigned to std::cout << str << '\n';}
Right Value reference Declaration &&
-1. the right value reference declaration can distinguish between a left value and a right value.
-2. reference the right value until the implementation of the Move semantics. It can Move the resources of temporary objects (which cannot be referenced generally) to other places.
-3. the right value reference can also be used to extend the lifecycle of a temporary object,
#include
#include
int main(){ std::string s1 = "Test";// std::string&& r1 = s1; // error: can't bind to lvalue const std::string& r2 = s1 + s1; // okay: lvalue reference to const extends lifetime// r2 += "Test"; // error: can't modify through reference to const std::string&& r3 = s1 + s1; // okay: rvalue reference extends lifetime r3 += "Test"; // okay: can modify through reference to non-const std::cout << r3 << '\n';}
-4. if the function has an overload of the left and right values, the call will match the call. If the left value is used, the left value is used. If the right value is used, the right value is used. this will support the implementation of moving Constructor and moving Assignment.
#include
#include
void f(int& x){ std::cout << "lvalue reference overload f(" << x << ")\n";}void f(const int& x){ std::cout << "lvalue reference to const overload f(" << x << ")\n";}void f(int&& x){ std::cout << "rvalue reference overload f(" << x << ")\n";}int main(){ int i = 1; const int ci = 2; f(i); // calls f(int&) f(ci); // calls f(const int&) f(3); // calls f(int&&) // would call f(const int&) if f(int&&) overload wasn't provided f(std::move(i)); // calls f(int&&)}