[C++11]_[初级]_[左值引用声明和右值引用声明]

来源:互联网 发布:极品泰版球衣淘宝店 编辑:程序博客网 时间:2024/05/21 17:16

场景:

  1. 在 remove_reference 结构体中能看到右值引用的身影 &&, 那么这里的右值引用到底有什么用呢?
  2. 经常也发现int& 和int&& 这两种类似的应用类型,第一种是左值引用声明,第二种是右值引用声明.
  3. 以下的例子直接参考的 cppreference,已经写的很完整了,没必要重新写.

参考:

1.Reference declaration
2.Rvalue Reference Declarator: &&
3.Lvalue Reference Declarator: &

语法

左值引用声明: & attr(optional) declarator (1)
右值引用声明: && attr(optional) declarator (2) (since C++11)

左值引用声明 &

–1. 左值引用可以理解为对象的别名, 左值引用必须被初始化而且不能被重新赋值.

#include <iostream>#include <string>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. 在调用函数时,可以被用来作为引用参数.

#include <iostream>#include <string>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. 当一个函数的返回值是左值时, 这个函数的调用的表达式可以被认为是一个左值表达式.

#include <iostream>#include <string>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';}

右值引用声明 &&

–1. 右值引用声明可以区别一个左值和右值.
–2. 右值引用直至Move语义的实现, 它可以把临时对象(一般不能引用)的资源移动到其他地方去.

–3. 右值引用也可以用来扩展临时对象的生命周期,

#include <iostream>#include <string>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. 如果函数有左值和右值引用的重载,调用时会匹配调用, 传左值调用左值重载, 右值调用右值重载. 这样就可以支持Move Constructor 和 Move Assignment 的实现.

#include <iostream>#include <utility>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&&)}
0 0