C++ 右值引用T&&

25 阅读2分钟

右值引用T&&

绑定到右值。

  • 关于右值引用的概念理解
    • 右值本身是不可修改的量,但右值引用变量本身是一个左值,有内存地址,生命周期
    • 并不是“先有一个右值,再给它创建一个叫右值引用的东西”,而是“右值引用这种类型,本身就是用来绑定右值的”。
    • 右值引用不等同于右值的引用,而是只能对右值进行右值引用.
    • 区分这个概念的关键在于,右值引用只能作用于右值,左值是不能进行右值引用的操作的。 如果需要对一个左值进行右值引用操作,那就要用std::move将之转为右值。
    #include <iostream>
    using namespace std;
    
    void func_rvalue(int&& rval) { cout << rval << endl; } 
    //这个函数只能接收右值,因为入参设定为参数的右值引用。只有右值才能被右值引用。左值作为参数输入进行右值引用会编译报错。
    
    int main() {
        
        int&& ref_b = 30; // ref_b是右值引用类型,ref_b绑定到右值30。即便ref_b绑定到右值,这个变量本身照样是一个左值。
        //因此 &ref_b 是不会报错的,&ref_b可以寻址。
        cout << &ref_b << endl;
        //但func_rvalue(ref_b);会出现编译报错。
        //因为 ref_b是左值,无法进行右值引用操作。
        func_rvalue(30);//30作为字面量是右值,这样的入参给到函数调用是可行的。
            //要想正确实现func_rvalue(ref_b); 应预先对ref_b用std::move(ref_b)进行右值转换。
            func_rvalue(std::move(ref_b));
        return 0;
    
    }
    

在模板中,T&&auto&&是万能引用。

#include <iostream>
using namespace std;

template <typename T>
void func(T&& val) {
    val += 10;
    cout << val << endl;
}

int main() {
    int a = 5;
    func(a); //万能引用,绑定左值。
    func(10); //万能引用,绑定右值。
    auto&& ref1 = a;
    auto&& ref2 = 20;
    return 0;
}

C++中的&&是右值引用,除了在模板和auto&&中可以作为万能引用之外,&&都只能处理右值的引用,涉及到左值的情况要用std::move处理转成右值引用类型。值得注意的是 const/volatile T&&/auto&& 是纯右值引用。(const 和 volatile 可单独修饰,也可组合修饰(const volatile),无论哪种组合,只要附加了这两个限定符,对应的 && 类型就只能是纯右值引用。)