1 什么是右值引用
int a = 4;
這里面a是左值,4是右值,一般的引用都只能設(shè)置為左值的引用
int& b = a;
b就是一個(gè)左值引用變量,意思為定義一個(gè)變量,綁定一個(gè)左值。顧名思義,右值引用的意思就是定義一個(gè)變量,綁定一個(gè)右值,cpp11里面的定義如下:
int&& a = 4;
如果定義:
int& a = 4;
會(huì)報(bào)錯(cuò):Non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'
立即數(shù),函數(shù)返回的值等都是右值。
2 移動(dòng)語意
右值引用的引入帶來的兩個(gè)好處,移動(dòng)語意和完美轉(zhuǎn)發(fā)。移動(dòng)語意可以在某些情況下節(jié)省拷貝次數(shù):舉例:
vector<int> v1 = {1,2,3};
vector<int> v2 = v1;
v2 = v1這個(gè)操作做了如下幾個(gè)操作, 構(gòu)造v2,之后將v1的所有元素拷貝到v2,如果我們不想繼續(xù)使用v1了,還需把v1銷毀。在cpp11中,可以直接使用如下做法:
vector<int> v1 = {1,2,3};
vector<int> v2 = vector(std::move(v1));
// 這個(gè)操作會(huì)同時(shí)給v2賦值,并且清空v1,這個(gè)其實(shí)是調(diào)用了v2的移動(dòng)構(gòu)造函數(shù)
標(biāo)準(zhǔn)庫源代碼如下:
/// Move constructor with alternative allocator
vector(vector&& __rv, const allocator_type& __m)
noexcept(_Alloc_traits::_S_always_equal())
: _Base(std::move(__rv), __m)
{
if (__rv.get_allocator() != __m)
{
this->_M_impl._M_finish =
std::__uninitialized_move_a(__rv.begin(), __rv.end(),
this->_M_impl._M_start,
_M_get_Tp_allocator());
__rv.clear();
}
}
// 最后會(huì)將右值引用入?yún)lear
右值引用也有延長(zhǎng)生命周期的作用。
3 通用引用
編譯器允許使用 A&& a的傳參方式去傳遞一個(gè)左值的引用,使用的方法是通過模板編程實(shí)現(xiàn)的:T&& 的作用主要是保持值類別進(jìn)行轉(zhuǎn)發(fā),參數(shù)既可以是左值引用,也可以是右值引用,所以也被叫做通用引用。具體做法是:
- 判斷是左值還是右值。
- 保留類型
- 強(qiáng)制轉(zhuǎn)換為左值或者右值。
4 完美轉(zhuǎn)發(fā)
所謂的完美轉(zhuǎn)發(fā)就是,左值引用轉(zhuǎn)發(fā)后還是左值引用,右值引用轉(zhuǎn)發(fā)后還是右值引用。
std::forward();
什么情況下需要完美轉(zhuǎn)發(fā)呢:
但不是所有情況都這么簡(jiǎn)單。
比如像make_unique<T>(arg)這種泛型工具,
其中一步是以arg為參數(shù)調(diào)用T的構(gòu)造函數(shù)。
make_unique的作用就是避免用戶直接調(diào)用T的構(gòu)造函數(shù),
所以沒法讓調(diào)用方改成直接調(diào)用。
不知道T的構(gòu)造函數(shù)支持哪些 lvalue / rvalue 參數(shù),
所以必須按原樣轉(zhuǎn)發(fā),
不能全都當(dāng)作 lvalue 或者全都當(dāng)作 rvalue。
所以只能轉(zhuǎn)發(fā),而且必須是“完美”轉(zhuǎn)發(fā)。
作者:d41d8c
鏈接:https://www.zhihu.com/question/348291815/answer/839048206
來源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
大意就是make_unique這種函數(shù),本身就是幫助你調(diào)用別人的構(gòu)造函數(shù),肯定只能是你想怎么調(diào),它就怎么調(diào),你是想傳左值引用還是右值引用,他都只能照辦,所以就有了完美轉(zhuǎn)發(fā)。