13拷貝控制
13.1拷貝椿息、賦值與銷毀
13.1.1拷貝構(gòu)造函數(shù)
拷貝構(gòu)造函數(shù)的第一個參數(shù)必須是引用類型可训。
使用拷貝初始化時蟆豫,我們要求編譯器將右側(cè)運(yùn)算對象拷貝到正在創(chuàng)建的對象中棍潘,如果需要的畫還要進(jìn)行類型轉(zhuǎn)換裕偿。
在函數(shù)調(diào)用過程中尊剔,具有非引用類型的參數(shù)要進(jìn)行拷貝初始化精偿。拷貝構(gòu)造函數(shù)被用來初始化非引用類型參數(shù)赋兵。
我們使用explicit就不要考慮是拷貝初始化還是直接初始化了笔咽。
13.1.2拷貝賦值運(yùn)算符
如果運(yùn)算符是一個成員函數(shù),其左側(cè)運(yùn)算對象就綁定到隱式的this參數(shù)霹期。右側(cè)運(yùn)算對象作為顯示參數(shù)傳遞叶组。賦值運(yùn)算符應(yīng)該返回一個指向左側(cè)運(yùn)算對象的引用。
13.1.3析構(gòu)函數(shù)
構(gòu)造函數(shù)初始化對象的非static數(shù)據(jù)成員历造;析構(gòu)函數(shù)釋放對象使用的資源甩十,并銷毀對象的非static數(shù)據(jù)成員。對一個給定類只會有唯一一個析構(gòu)函數(shù)吭产。
在一個析構(gòu)函數(shù)中侣监,首先執(zhí)行函數(shù)體,然后銷毀成員臣淤。成員按初始化順序的逆序銷毀橄霉。析構(gòu)函數(shù)釋放對象在生存期分配的所有資源。
隱式銷毀一個內(nèi)置指針類型成員不會delete它所指向的對象邑蒋。
13.1.4三五法則
需要拷貝操作的類也需要賦值操作姓蜂,反之亦然。
13.1.5使用=default
13.1.6阻止拷貝
為什么拷貝医吊、賦值钱慢、銷毀的合成版本會阻止其操作?
對某些類來說卿堂,這些操作沒有合理的意義束莫,所以得采用某種機(jī)制阻止拷貝或賦值。例如iostream類阻止了拷貝草描。
定義刪除的函數(shù)
析構(gòu)函數(shù)不能是刪除的成員览绿,可定義,但帶來的后果是災(zāi)難性的陶珠。
合成的拷貝控制成員可能是刪除的挟裂。
13.2拷貝控制和資源管理
13.2.1行為像值的類
13.2.2行為像指針的類
定義引用計(jì)數(shù)來決定什么時候delete。將計(jì)算器保存在動態(tài)內(nèi)存中揍诽。
13.3交換操作
底層利用std::swap交換
在賦值運(yùn)算符中使用swap
13.6對象移動
某些情況下通過對象移動能夠“拷貝诀蓉、賦值”能夠節(jié)省很多資源栗竖。
13.6.1右值引用&&
右值引用必須綁定到右值的引用,利用&&來獲得右值引用渠啤。
左值=右值狐肢;一個左值表達(dá)式表示的是一個對象的身份(地址),而右值表達(dá)式表示的是對象的值沥曹。
常規(guī)引用為左值引用份名。不能將其綁定到要求轉(zhuǎn)換的表達(dá)式、字面常量或是返回右值的表達(dá)式妓美。
右值引用也不過是對象的另一個名字而已僵腺,可以綁定到左值引用不能綁定的對象上,但是不能將一個右值引用直接綁定到一個左值上壶栋。
左值持久辰如;右值短暫
左值具有持久的狀態(tài),而右值要么是字面常量贵试,要么是在表達(dá)式求值過程中創(chuàng)建的臨時對象琉兜。
13.6.2移動構(gòu)造函數(shù)和移動賦值運(yùn)算符
移動構(gòu)造函數(shù)第一個參數(shù)是該類的一個右值引用。直接移動毙玻,然后在析構(gòu)實(shí)參豌蟋。
noexcept(通知標(biāo)準(zhǔn)庫不拋出任何異常),必須在頭文件的聲明中和定義中(如果定義在類外)都指定noexcept桑滩。
移動構(gòu)造函數(shù)不分配任何新內(nèi)存梧疲。
移動賦值運(yùn)算符是先清空本身,在移動施符,在析構(gòu)實(shí)參往声。
與拷貝操作不同,移動操作用于不會隱式定義為刪除的函數(shù)戳吝。
用拷貝構(gòu)造函數(shù)代替移動構(gòu)造函數(shù)幾乎肯定是安全的(賦值也是如此)。
移動右值拷貝左值贯涎,但如果沒有移動構(gòu)造函數(shù)听哭,右值也被拷貝。
移動迭代器
一個迭代器一般解引用運(yùn)算符返回一個指向元素的左值塘雳。而移動迭代器的解引用運(yùn)算符生成有個右值引用陆盘。
13.6.3右值引用和成員函數(shù)
實(shí)參類型決定了新元素是拷貝還是移動到容器中。