左值引用和右值引用
C++11 朝码夕解: move 和 forward

# 左值和右值

  • 左值 ( lvalue ):非临时变量。在内存有确定存储地址、有变量名,表达式结束依然存在的值。
    int a=10;              	//a 为非常量左值(有确定存储地址,也有变量名)
    const int a1=10;      //a1 为常量左值(有确定存储地址,也有变量名)
    const int a2=20;      //a2 为常量左值(有确定存储地址,也有变量名)
  • 右值 ( rvalue ):临时变量。在内存没有确定存储地址、没有变量名,表达式结束就会销毁的值。
    int a=10;              	// 10 为非常量右值
    const int a1=10;      
    const int a2=20;      
    a1+a2               	// (a1+a2) 为常量右值

左值引用和右值引用是指左值或者右值的型别,左值的型别可以为左值引用,也可以为右值引用。右值的型别可以为右值引用,但不能为左值引用,因为左值引用仅能引用左值 ( const 修饰的左值引用可以引用右值, 因为函数参数重 const 修饰的参数,编译器会为传入的右值创建临时变量,所以 cosnt 修饰的左值引用其实是引用的这个临时变量)。右值引用仅能引用纯右值。

# std::move 和 std::forward

  • std::move
    1. std::move 强制转换为右值。
      template <class T>
      typename remove_reference<T>::type&& move(T&& param){
          typedef typename remove_reference<T>::type _Up;
          return static_cast<_Up&&>(param);
      }
      推导后的 param 的类型为 T&(实参为左值时) 或 T (实参为右值时)。返回时将 param 去除引用后强制转换为 T&& 型别,最终的返回结果为 T&& 型别的右值。
    2. std::move转 换为右值时,若保留了常量性 const ,则不会调用移动构造函数,而是调用复制构造函数。
  • std::forward
    std::forward 使用时需要具化: std::forward<T>();
template<typename T1, typename T2>
void set(T1 && var1, T2 && var2){
  m_var1 = std::forward<T1>(var1);
  m_var2 = std::forward<T2>(var2);
}
//when var1 is an rvalue, std::forward<T1> equals to static_cast<[const] T1 &&>(var1)
//when var1 is an lvalue, std::forward<T1> equals to static_cast<[const] T1 &>(var1)

如果外面传来了 rvalue 临时变量,它就转发 rvalue 并且启用 move 语义.
如果外面传来了 lvalue , 它就转发 lvalue 并且启用复制。然后它也还能保留 const

# 区分右值引用和万能引用

万能引用的条件:

  1. T&&
  2. T 的类型由推导而来
template <typename T>
void f(const T&& param); //param 是个右值引用
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

ArMiku@安然 微信支付

微信支付

ArMiku@安然 支付宝

支付宝

ArMiku@安然 贝宝

贝宝