C++ 左值引用和右值引用之间的转换


int retVal(int &&v)
{
    cout << "右值引用:";
    return v;
}

int retVal(int &v)
{
    cout << "左值引用:";
    return v;
}

int retVal(const int &v)
{
    cout << "const 左值引用:";
    return v;
}

int getVal()
{
    return 999;
}


// 主函数
int main()
{
    int a = 100;
    int &b = a;
    
    cout << retVal(static_cast<int &&>(a)) << endl;
    cout << retVal(static_cast<int &&>(b)) << endl;
    cout << retVal(110) << endl;

    system("pause");
    return EXIT_SUCCESS;
}

输出:

右值引用:100
右值引用:100
右值引用:110
请按任意键继续. . .

可见,上面三个输出,都是精准匹配到的是int retVal(int &&v)函数。另外左值或左值引用可以通过static_cast<int &&>()强转成右值类型(这个是 std::move 的基础?);反过来右值不能通过static_cast<int &>()转成左值引用。如,cout << retVal(static_cast<int&>(getVal())) << endl; 这样子会报错。

下面我们注释掉右值函数:


//int retVal(int &&v)
//{
//    cout << "右值引用:";
//    return v;
//}

int retVal(int &v)
{
    cout << "左值引用:";
    return v;
}

int retVal(const int &v)
{
    cout << "const 左值引用:";
    return v;
}

int getVal()
{
    return 999;
}

NS_END

int main()
{
    int a = 100;
    int &b = a;
    
    cout << retVal(static_cast<int &&>(a)) << endl;
    cout << retVal(static_cast<int &&>(b)) << endl;
    cout << retVal(110) << endl;

    system("pause");
    return EXIT_SUCCESS;
}

输出:

const 左值引用:100
const 左值引用:100
const 左值引用:110
请按任意键继续. . .

可见,编译器匹配到的是int retVal(const int &v)函数。也就是说,int && 可以转换成const int &v类型。经测试,不能转换成int &v类型。

Note: 区分移动和拷贝的重载函数通常有一个版本接受一个const T&,而另一个版本接受一个 T&&。 ——《C++ Primer》 P482

所以,一般会重载两个函数,一个是右值引用参数,另一个是 const 左值引用参数。

另外, 函数尾后引用重载版本声明样式如下:

class Foo {
public:
    Foo sorted() &&;     // 可用于可改变的右值
    Foo sorted()const &; // 可用于任何类型的Foo
private:
    vector<int> data;

——《C++ Primer》 P484

posted @ 2024-11-13 22:49  double64  阅读(1)  评论(0编辑  收藏  举报