13.1 拷貝、賦值與銷毀(1)

拷貝構(gòu)造函數(shù)

??如果一個(gè)構(gòu)造函數(shù)的第一個(gè)參數(shù)是自身類類型的引用荔燎,且任何額外參數(shù)都有默認(rèn)值,則此構(gòu)造函數(shù)是拷貝構(gòu)造函數(shù)艰山。

class Foo {
public:
      Foo();  //默認(rèn)構(gòu)造函數(shù)
      Foo(const Foo&);  //拷貝構(gòu)造函數(shù)
      //...
};

??拷貝構(gòu)造函數(shù)的第一個(gè)參數(shù)必須是引用類型湖雹,雖然我們可以定義一個(gè)接受非const引用的拷貝構(gòu)造函數(shù),但此參數(shù)幾乎總是一個(gè)const的引用曙搬∷だ簦拷貝構(gòu)造函數(shù)在幾種情況下都會(huì)被隱式地使用。因此纵装,拷貝構(gòu)造函數(shù)通常不應(yīng)該是explicit的征讲。

??合成拷貝構(gòu)造函數(shù)
??對(duì)某些類來說,合成拷貝構(gòu)造函數(shù)用來阻止我們拷貝該類類型的對(duì)象橡娄,而一般情況诗箍,合成的拷貝構(gòu)造函數(shù)會(huì)將其參數(shù)的成員逐個(gè)拷貝到正在創(chuàng)建的對(duì)象中。編譯器從給定對(duì)象中依次將每個(gè)非static成員拷貝到正在創(chuàng)建的對(duì)象中挽唉。

??拷貝初始化
??直接初始化與拷貝初始化的差異:

string dots(10,'.');  //直接初始化
string s(dots);  //直接初始化
string s2=dots;  //拷貝初始化
sttring null_book="9-999-99999-9";  //拷貝初始化
string nines=string(100,'9');  //拷貝初始化

??當(dāng)使用直接初始化時(shí)滤祖,我們實(shí)際上是要求編譯器使用普通的函數(shù)匹配來選擇與我們提供的參數(shù)最匹配的構(gòu)造函數(shù),當(dāng)我們使用拷貝初始化時(shí)瓶籽,我們要求編譯器將右側(cè)運(yùn)算對(duì)象拷貝到正在創(chuàng)建的對(duì)象中匠童,如果需要的話還要進(jìn)行類型轉(zhuǎn)換∷芩常拷貝初始化通常使用拷貝構(gòu)造函數(shù)來完成汤求。
??除了使用“=”定義變量時(shí)會(huì)發(fā)生拷貝初始化俏险,還有以下情況:
??1、將一個(gè)對(duì)象作為實(shí)參傳遞給一個(gè)非引用類型的形參
??2扬绪、從一個(gè)返回類型為非引用類型的函數(shù)返回一個(gè)對(duì)象
??3竖独、用花括號(hào)列表初始化一個(gè)數(shù)組中的元素或一個(gè)聚合類的成員

??拷貝初始化的限制
??如果我們使用的初始化值要求通過一個(gè)explicit構(gòu)造函數(shù)來進(jìn)行類型轉(zhuǎn)換,那么使用拷貝初始化還是直接初始化就不是無關(guān)緊要的了:

vector<int> v1(10);  //正確:直接初始化
vector<int> v2=10;  //錯(cuò)誤:接受大小參數(shù)的構(gòu)造函數(shù)是explicit的
void f(vector<int>);  //f的參數(shù)進(jìn)行拷貝初始化
f(10);  //錯(cuò)誤:不能用一個(gè)explicit的構(gòu)造函數(shù)拷貝一個(gè)實(shí)參
f(vecotr<int> (10));  //正確:從一個(gè)int直接構(gòu)造一個(gè)臨時(shí)vector

??編譯器可以繞過拷貝構(gòu)造函數(shù)
??在拷貝初始化過程中挤牛,編譯器可以跳過拷貝/移動(dòng)構(gòu)造函數(shù)莹痢,直接創(chuàng)建對(duì)象:

string null_book="9-999-99999-9"  //拷貝初始化

改寫為:

string null_book=("9-999-99999-9");  //編譯器略過了拷貝構(gòu)造函數(shù)

拷貝賦值運(yùn)算符

??與類控制其對(duì)象如何初始化一樣,類也可以控制其對(duì)象如何賦值:

Sales_data trans,accum;
trans=accum;  //使用Sales_data的拷貝賦值運(yùn)算符

??重載賦值運(yùn)算符
??重載運(yùn)算符的本質(zhì)上是函數(shù)赊颠,其名字由operator關(guān)鍵字后接表示要定義的運(yùn)算符的符號(hào)組成格二。因此,賦值運(yùn)算符就是一個(gè)名為operator=的函數(shù)竣蹦。例如:

class Foo {
public:
Foo& operator=(const Foo&);  //賦值運(yùn)算符
//...
};

??合成拷貝賦值運(yùn)算符
??與處理拷貝構(gòu)造函數(shù)一樣顶猜,如果一個(gè)類未定義自己的拷貝賦值運(yùn)算符,編譯器會(huì)為它生成一個(gè)合成拷貝賦值運(yùn)算符痘括。合成拷貝運(yùn)算符返回一個(gè)指向其左側(cè)運(yùn)算對(duì)象的引用长窄。例如:

//等價(jià)于合成拷貝賦值運(yùn)算符
Sales_data&
Sales_data::operator=(const Sales_data &rhs)
{
    bookNo=rhs.bookNo;  //調(diào)用string::operator=
    units_sold=rhs.units_sold;  //使用內(nèi)置的int賦值
    revenue=rhs.revenue;  //使用內(nèi)置的double賦值
    return *this;  //返回一個(gè)此對(duì)象的引用
}

析構(gòu)函數(shù)

??析構(gòu)函數(shù)執(zhí)行與構(gòu)造函數(shù)相反的操作:構(gòu)造函數(shù)初始化對(duì)象的非static成員,還可能做一些其他工作纲菌;析構(gòu)函數(shù)釋放對(duì)象使用的資源挠日,并銷毀對(duì)象的非static數(shù)據(jù)成員。

class Foo {
public:
      ~Foo();  //析構(gòu)函數(shù)
      //...
};

??由于析構(gòu)函數(shù)不接受參數(shù)翰舌,因此它不能被重載嚣潜。

??析構(gòu)函數(shù)完成什么工作
??在一個(gè)析構(gòu)函數(shù)中,首先執(zhí)行函數(shù)體椅贱,然后銷毀成員懂算,成員按初始化順序的逆序銷毀,在對(duì)象最后一次使用之后庇麦,析構(gòu)函數(shù)的函數(shù)體可執(zhí)行類設(shè)計(jì)者希望執(zhí)行的任何收尾工作计技。在一個(gè)析構(gòu)函數(shù)中,不存在類似構(gòu)造函數(shù)中初始化列表的東西來控制成員如何銷毀山橄,析構(gòu)部分是隱式的垮媒。

??什么時(shí)候會(huì)調(diào)用析構(gòu)函數(shù)
??無論何時(shí)一個(gè)對(duì)象被銷毀,就會(huì)自動(dòng)調(diào)用其析構(gòu)函數(shù)航棱,由于析構(gòu)函數(shù)自動(dòng)運(yùn)行睡雇,我們的程序可以按需要分配資源,而無須擔(dān)心何時(shí)釋放這些資源饮醇。

??合成析構(gòu)函數(shù)
??當(dāng)一個(gè)類未定義自己的析構(gòu)函數(shù)時(shí)入桂,編譯器會(huì)為它定義一個(gè)合成析構(gòu)函數(shù)。對(duì)于某些類驳阎,合成析構(gòu)函數(shù)被用來阻止該類型的對(duì)象被銷毀,如果不是這種情況,合成析構(gòu)函數(shù)的函數(shù)體就為空呵晚。
??在(空)析構(gòu)函數(shù)執(zhí)行完畢后蜘腌,成員會(huì)被自動(dòng)銷毀,析構(gòu)函數(shù)自身并不直接銷毀成員饵隙,成員是在析構(gòu)函數(shù)體之后隱含的析構(gòu)階段被銷毀的撮珠,在整個(gè)對(duì)象銷毀過程中,析構(gòu)函數(shù)體是作為成員銷毀步驟之外的另一部分而進(jìn)行的金矛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末芯急,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子驶俊,更是在濱河造成了極大的恐慌娶耍,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饼酿,死亡現(xiàn)場(chǎng)離奇詭異榕酒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)故俐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門想鹰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人药版,你說我怎么就攤上這事辑舷。” “怎么了槽片?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵何缓,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我筐乳,道長(zhǎng)歌殃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任蝙云,我火速辦了婚禮氓皱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘勃刨。我一直安慰自己波材,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布身隐。 她就那樣靜靜地躺著廷区,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贾铝。 梳的紋絲不亂的頭發(fā)上隙轻,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天埠帕,我揣著相機(jī)與錄音,去河邊找鬼玖绿。 笑死敛瓷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的斑匪。 我是一名探鬼主播呐籽,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蚀瘸!你這毒婦竟也來了狡蝶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤贮勃,失蹤者是張志新(化名)和其女友劉穎贪惹,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衙猪,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡馍乙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了垫释。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丝格。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖棵譬,靈堂內(nèi)的尸體忽然破棺而出显蝌,到底是詐尸還是另有隱情,我是刑警寧澤订咸,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布曼尊,位于F島的核電站,受9級(jí)特大地震影響脏嚷,放射性物質(zhì)發(fā)生泄漏骆撇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一父叙、第九天 我趴在偏房一處隱蔽的房頂上張望神郊。 院中可真熱鬧,春花似錦趾唱、人聲如沸涌乳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夕晓。三九已至,卻和暖如春悠咱,著一層夾襖步出監(jiān)牢的瞬間蒸辆,已是汗流浹背征炼。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吁朦,地道東北人柒室。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像逗宜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子空骚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353