1、引用類型
引用為對(duì)象定義了一個(gè)別名全蝶,與指針相比:引用必須初始化、不可以被重新賦值寺枉、且無(wú)法多級(jí)引用抑淫。布袋戲中,苗疆的風(fēng)逍遙
道號(hào)風(fēng)中捉刀
型凳,廣義上來說也是一個(gè)引用hhhhhhh
1.1 左值引用
膚淺的講丈冬,所謂左值嘱函,能夠出現(xiàn)在等號(hào)左邊甘畅,它們有名字,且可以取地址往弓。左值引用可以簡(jiǎn)單理解為:對(duì)能夠出現(xiàn)在=
左邊對(duì)象的引用疏唾。
例如: 以下fengXiaoYao
就是左值,fengZhongZhuoDao
就是左值引用函似。
int fengXiaoYao=666;
int &fengZhongZhuoDao = fengXiaoYao;
1.2 右值引用
可以對(duì)照左值槐脏,理解右值。所謂右值撇寞,只能出現(xiàn)在等號(hào)右邊顿天,沒有名字也無(wú)法取地址堂氯。蠻像布袋戲里的妖道角,通常是將會(huì)被銷毀的臨時(shí)對(duì)象牌废。對(duì)這類右值的引用也就是右值引用咽白。其定義如下:
//簡(jiǎn)單工廠函數(shù)
YDJ YaoDaoJiaoFactory::generate()
{
return YDJ();
}
//右值引用獲取`YDJ`對(duì)象
YDJ&& tdj = yaoDaoJiaoFactory.generate();
眾所周知,布袋戲中的妖道角是每天零點(diǎn)定時(shí)刷新的鸟缕,這里用一個(gè)工廠函數(shù)批量生產(chǎn)妖道角晶框,工廠函數(shù)返回的是一個(gè)無(wú)名的YDJ
對(duì)象,即右值對(duì)象懂从。對(duì)右值的引用授段,稱為右值引用。
1.3 通用引用
即可以綁定左值番甩,又可以綁定右值的引用稱為通用引用侵贵。
值得注意的時(shí),通用引用與右值引用有著相同的定義形式对室,即:
T&&
兩者以如下新式區(qū)分:
1模燥、聲明標(biāo)準(zhǔn)為嚴(yán)格的:type&&
(例如:T&&
、auto&&
)掩宜。
2蔫骂、type
需要被推導(dǎo)得知,即有類型推導(dǎo)發(fā)生牺汤。
對(duì)于通用引用辽旋,如果它被右值初始化,就會(huì)成為右值引用檐迟;如果它被左值初始化补胚,就會(huì)成為左值引用。
1.4 引用折疊
正如前文只提到的那樣追迟,引用是一級(jí)的溶其,引用
的引用
在編譯過程中不被允許。
但如果考慮引用的引用敦间,則存在如下四種情況:
1瓶逃、左值的左值: & &
2、左值的右值:& &&
3廓块、右值的左值:&& &
4厢绝、右值得右值:&& &&
引用折疊就是用來將以上引用的引用折疊為單個(gè)引用,其規(guī)則如下:
如果任一引用為左值引用带猴,則結(jié)果為左值引用昔汉。否則(即,如果引用都是右值引用)拴清,結(jié)果為右值引用靶病。
因此会通,上述四種情況下,只有最后一種的結(jié)果為右值引用娄周。
可具體考慮如下實(shí)例:
template<typename T>
void throughTheGrove(T&& ydj) {
……
}
這里渴语,我們定義了一個(gè)函數(shù)模板:穿過小樹林。作為布袋戲中最為危險(xiǎn)的場(chǎng)景之一昆咽,小樹林急急而奔的死亡率一直居高不下驾凶。
現(xiàn)在我們分別以兩種方式傳遞一個(gè)妖道角(YDJ)
對(duì)象給穿過小樹林(throughTheGrove)
函數(shù):
throughTheGrove(ydj); // (1)
throughTheGrove(YDJ()); // (2)
考慮式(1)
與式(2)
有何不同。
對(duì)于式(1)
:傳入一個(gè)左值對(duì)象ydj
,T
被推導(dǎo)為YDJ &
,則throughTheGrove
的形參類型會(huì)被推導(dǎo)為YDJ& &&
,從而觸發(fā)引用折疊掷酗,最終得到新參類型'YDJ &',即左值引用调违。
對(duì)于式(2)
:傳遞一個(gè)右值對(duì)象YDJ()
,則按照模板的推導(dǎo)規(guī)則泻轰,T被推導(dǎo)為YDJ
,形參類型會(huì)被推導(dǎo)為YDJ&&
技肩,即右值引用。
注意:式(2)
中浮声,盡管void throughTheGrove(T&& ydj)
的形參類型被推導(dǎo)為YDJ&& ydj
,形參ydj
仍是左值(形參是左值這總是成立)虚婿。
可以進(jìn)行如下測(cè)試:
//定義YDJ左值與右值的兩個(gè)重載:
void printYDJ(YDJ&& ydj) {
printf("the right YDJ\n");
}
void printYDJ(YDJ& ydj) {
printf("the left YDJ\n");
}
//在模板函數(shù)中調(diào)用:throughTheGrove(std::move(tdj));
template<typename T>
void throughTheGrove(T&& ydj) {
printYDJ(ydj);
}
其打印結(jié)果如下:
the left YDJ