# 左值引用&右值引用

## 左值引用
对于非const的左值引用，只能匹配左值。对于const的左值引用(也叫 常引用)，可以匹配左值和右值
```cpp
int a = 3;
int& ra = a; // 只能匹配左值
const int& cra = 10; // 可以匹配右值
```

## 右值引用

### 初始化

右值引用仅可使用 `rvalue` 进行初始化
```cpp
Foo func2()
{
  Foo f1("AAA");
  return f1;
}

int main()
{
  int && r1 = 3; // 1. 引用字面量
  Foo && r2 = func2(); // 2. 引用临时变量(函数返回值)
  Foo && r3 = Foo("BBB"); // 3. 引用临时变量(匿名变量)

  Foo f("CCC");
  Foo && r4 = std::move(f); // 4. 引用std::move的强制左值

  return 0;
}
```

### 值类别(value category) 和 变量类型 (variable type)

值(value) 和 变量(variable) 是两个独立的概念。
* 值 只有 类别 (category) 的划分，变量 只有 类型 (type) 的划分
* 值 不一定拥有 身份 (identity)，也不一定拥有 变量名（例如 表达式中间结果 i + j + k）

[值类别](https://en.cppreference.com/w/cpp/language/value_category)可以分为五种: lvalue, xvalue, prvalue, glvalue, rvalue.

[引用类型(Reference declaration)](https://en.cppreference.com/w/cpp/language/reference)属于一种[变量类型](https://en.cppreference.com/w/cpp/language/type), ex: 左值引用，右值引用，常引用。

`Foo&&`类型只是指明变量类型，并不能区分左右值。就好像对于`int i = 3;` 一样，`=`的左右都是`int`类型，但是左侧的`i`是左值，右侧的`3`的右值(prvalue)。 

### 右值引用初始化

右值引用和左值引用比起来，不同的地方在于初始化那一刻：**右值引用必须通过右值来初始化**。初始化完成之后，就没有什么特殊的了。

C++11有一个规则：**右值引用类型(形如Foo&&)的表达式，有名字的是左值；没有名字的是右值**。其实这也可以类比其他类型，命名变量(如局部变量、形参、全局变量)是左值；匿名变量(没有名字)是右值。

### 生命周期

通过 右值引用/常引用 初始化的右值，都可以将 [生命周期扩展 (lifetime extension)](https://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary)  到 绑定该右值的 引用的生命周期


```cpp
class Bar {
private:
    string s;
public:
    Bar(string a) : s(a) {
        cout << "Bar(string) " << s << endl;
    }
    ~Bar() {
        cout << "~Bar() " << s << endl;
    }
};
int main() {
    Bar("a");
    Bar&& rfb = Bar("b");
    cout << "end" << endl;
}

//    Output
//    Bar(string) a
//    ~Bar() a
//    Bar(string) b
//    end
//    ~Bar() b
```
对于`a`未被引用的右值, 在执行完当前行后，就会被析构。对于被`rfb`的右值引用的`b`，生命周期绑定至`rfb`的生命周期

## ref
1. https://www.yuanguohuo.com/2018/05/25/cpp11-rvalue-ref/
2. https://murphypei.github.io/blog/2020/02/right-reference
