C++ 左值引用和右值引用之間的轉換

double64發表於2024-11-13

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

相關文章