C++11之右值引用(一):從左值右值到右值引用

C++98中規定了左值和右值的概念,但是一般程序員不需要理解的過於深入,因爲對於C++98,左值和右值的劃分一般用處不大,但是到了C++11,它的重要性開始顯現出來。

C++98標準明確規定:

左值是可以取得內存地址的變量。

非左值即爲右值。

從這裏可以看出,可以執行&取地址的就是左值,其他的就是右值

這裏需要明確一點,能否被賦值不是區分C++左值和右值的區別

我們給出四個表達式:

string one("one");
const string two("two");
string three() { return "three"; }
const string four() { return "four"; }

這裏四個變量表達式,後面兩個是臨時變量,不可以取地址,所以屬於右值,前面兩個就是左值。

這裏寫出一個函數:

void test(const string &s)
{
    cout << "test(const string &s):" << s << endl;
}

然後進行測試:

test(one);
test(two);
test(three());
test(four());

編譯我們發現,這個test可以接受所有的變量。

我們使用另一個函數做測試:

void test(string &s)
{
    cout << "test(string &s):" << s << endl;
}

然後測試發現,只有one可以通過調用

然後我們同時提供兩個test函數,然後我們編譯運行發現:

test(string &s):one
test(const string &s):two
test(const string &s):three
test(const string &s):four

 

所以我們可以得出結論:

在C++中,const X&可以接受所有的變量

X &只可以接受普通變量

同時我們可以看出C++重載決議的一個特點:

當一個參數可以匹配多個函數時,總是匹配最精準的一個。

例如上面的one,它也可以接受const X&,但是當X&形式的參數存在時,立刻選擇後者。顯然後者是專門爲其準備的,二者的語義最爲符合。X&包含有一種修改語義,這與one是一致的

 

引入const屬性

 

上面的四個表達式,我們只討論了左值和右值,我們再加上const進行討論。

所以:

string one("one"); 屬於非const左值
const string two("two");   const左值
string three() { return "three"; } 非const右值
const string four() { return "four"; } const右值
左值右值的屬性與const是正交的。
現在引入一個問題,如果有時候需要區分四種變量,那麼該使用什麼方法?
前面的討論,我們知道X&可以用來區分one,但是剩下的三個都可以被const X&吞掉,顯然我們需要爲一些變量提供一些定製版本的參數,來讓不同的變量優先選擇不同的參數。
C++11提供了右值引用來專門區分右值,我們同時提供四個函數:
複製代碼
void test(const string &s)
{
    cout << "test(const string &s):" << s << endl;
}

void test(string &s)
{
    cout << "test(string &s):" << s << endl;
}

void test(string &&s)
{
    cout << "test(string &&s):" << s << endl;
}

void test(const string &&s)
{
    cout << "test(const string &&s):" << s << endl;
}
複製代碼

我們使用C++11進行編譯,發現:

test(string &s):one
test(const string &s):two
test(string &&s):three
test(const string &&s):four

我們得出最佳匹配

 

X & 匹配 非const左值

const X& 匹配 const左值

X && 匹配 非const右值

const X && 匹配 const右值

然後,我們可以採用逐個函數進行測試,發現:

X& 僅僅匹配 非const左值,這與之前的結論一致

const X& 可以匹配所有的表達式

X && 只可以匹配 非const右值

const X &&可以匹配const和非const 右值

OK,我們的問題解決,當我們需要區分右值的時候,就可以使用右值引用。

事實上,我們一般不需要const X &&,所以我們使用下列三種參數:

 

void test(string &s); 修改語義

void test(string &&s); 移動語義,後文介紹

void test(const string &s); 常量語義

這三種語義已經足夠,在C++98中我們只使用修改和常量語義,在C++11中,正是爲了實現移動語義,我們才需要區分右值,才需要引入右值引用

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章