這裏究竟發生了什麼?爲什麼這是一個錯誤?將int &&傳遞給f(int &&)
void f(int &&);
int && i = 5;
f(i);
這不是有點違反直覺嗎?
我期望i
是一個右值引用,所以能夠將它傳遞給f()
。但我得到一個錯誤;
從
int
到int &&
沒有已知的轉換所以我想i
不聲明後,右值引用?
這裏究竟發生了什麼?爲什麼這是一個錯誤?將int &&傳遞給f(int &&)
void f(int &&);
int && i = 5;
f(i);
這不是有點違反直覺嗎?
我期望i
是一個右值引用,所以能夠將它傳遞給f()
。但我得到一個錯誤;
從
int
到int &&
沒有已知的轉換所以我想i
不聲明後,右值引用?
這裏有一個基本的區別是和綁定。例如:
void f(int &&);
聲明的函數接受只能用一個rvalue參考將其初始化爲(類型轉換爲)int
的參數。
int && i = 5;
聲明只能與一個rvalue參考將其初始化爲(類型轉換爲)int
左值。因此,簡單來說,
f(i);
試圖通過左值參照的int
到功能僅接受一個int
rvalue引用。所以它不會編譯。
告訴編譯器投一個左到右值,從而利用move構造函數在適用情況下(雖然不是在int
的情況下),你可以使用std::move()
。
f(std::move(i));
在這種情況下,我會添加關於'std :: move'的信息。 – Zereges
@Zereges好主意。添加。 –
這幾乎是一個很好的答案,但稍微不準確。 _「聲明一個左值,只能賦值給一個int的右值引用。」_不,它不能被賦值任何東西,當然不是一個右值引用(因爲賦值給一個引用實際上賦值給它綁定的東西,但這是初始化不分配)。它聲明瞭一個右值參考類型的左值''i',它只能用一個右值(不是右值參考,右值)進行**初始化。 –
它有一個名字嗎?
可尋址嗎?
如果兩者的答案都是「是」,那麼這是一個L值。
在這個片段中:i
有一個名字,i
有一個地址(你可以寫&i
),所以它是一個l值。
f(&&)
獲取r值參考值作爲參數,因此您需要將l值轉換爲r值參考值,這可以通過std::move
完成。
f(std::move(i));
注意:也有一些沒有名字的左值。另外,「是否可尋址」是一個循環定義。通過「可尋址」,我假設你的意思是,「可以單一化並且應用於它」?然而一元'&&的定義包括它只能用於左值! –
恩,調查員也有名字.... – cpplearner
我明白你爲什麼會感到困惑。需要記住的是,只要你有一個變量名,你就有一個的l值。
所以,當你說:
int i = 0; // lvalue (has a name i)
而且還
int&& i = 0; // lvalue (has a name i)
那麼有什麼區別?
的int&&
可以僅結合一個r值這樣:
int n = 0;
int i = n; // legal
BUT
int n = 0;
int&& i = n; // BAD!! n is not an r-value
然而
int&& i = 5; // GOOD!! 5 is an r-value
在這個例子中傳遞i
時f()
你傳遞一個升值,而不是r值所以:
void f(int &&);
int&& i = 5; // i is an l-value
f(i); // won't accept l-value
的情況實際上是一個有點複雜,比我在這裏提出。如果你對這個更全面的解釋感興趣,那麼這個參考文件是非常全面的:http://en.cppreference.com/w/cpp/language/value_category
你希望會發生什麼?你想做什麼?你認爲'&&'在這種情況下意味着什麼? – Galik
@Galik,我在我的問題中增加了一些評論。 –
使用'std :: move()'得到一個右值引用。 –