本文主要介紹了拷貝構(gòu)造函數(shù)和賦值運(yùn)算符的區(qū)別,以及在什么時(shí)候調(diào)用拷貝構(gòu)造函數(shù)、什么情況下調(diào)用賦值運(yùn)算符。最后,簡(jiǎn)單的分析了下深拷貝和淺拷貝的問(wèn)題。
拷貝構(gòu)造函數(shù)和賦值運(yùn)算符
在默認(rèn)情況下(用戶沒(méi)有定義,但是也沒(méi)有顯式的刪除),編譯器會(huì)自動(dòng)的隱式生成一個(gè)拷貝構(gòu)造函數(shù)和賦值運(yùn)算符。但用戶可以使用delete
來(lái)指定不生成拷貝構(gòu)造函數(shù)和賦值運(yùn)算符,這樣的對(duì)象就不能通過(guò)值傳遞,也不能進(jìn)行賦值運(yùn)算。
class Person {public: Person(const Person& p) = delete; Person& operator=(const Person& p) = delete;private: int age; string name; };
上面的定義的類Person
顯式的刪除了拷貝構(gòu)造函數(shù)和賦值運(yùn)算符,在需要調(diào)用拷貝構(gòu)造函數(shù)或者賦值運(yùn)算符的地方,會(huì)提示_無(wú)法調(diào)用該函數(shù),它是已刪除的函數(shù)_。
還有一點(diǎn)需要注意的是,拷貝構(gòu)造函數(shù)必須以引用的方式傳遞參數(shù)。這是因?yàn)?,在值傳遞的方式傳遞給一個(gè)函數(shù)的時(shí)候,會(huì)調(diào)用拷貝構(gòu)造函數(shù)生成函數(shù)的實(shí)參。如果拷貝構(gòu)造函數(shù)的參數(shù)仍然是以值的方式,就會(huì)無(wú)限循環(huán)的調(diào)用下去,直到函數(shù)的棧溢出。
何時(shí)調(diào)用
拷貝構(gòu)造函數(shù)和賦值運(yùn)算符的行為比較相似,都是將一個(gè)對(duì)象的值復(fù)制給另一個(gè)對(duì)象;但是其結(jié)果卻有些不同,拷貝構(gòu)造函數(shù)使用傳入對(duì)象的值生成一個(gè)新的對(duì)象的實(shí)例,而賦值運(yùn)算符是將對(duì)象的值復(fù)制給一個(gè)已經(jīng)存在的實(shí)例。這種區(qū)別從兩者的名字也可以很輕易的分辨出來(lái),拷貝構(gòu)造函數(shù)也是一種構(gòu)造函數(shù),那么它的功能就是創(chuàng)建一個(gè)新的對(duì)象實(shí)例;賦值運(yùn)算符是執(zhí)行某種運(yùn)算,將一個(gè)對(duì)象的值復(fù)制給另一個(gè)對(duì)象(已經(jīng)存在的)。調(diào)用的是拷貝構(gòu)造函數(shù)還是賦值運(yùn)算符,主要是看是否有新的對(duì)象實(shí)例產(chǎn)生。如果產(chǎn)生了新的對(duì)象實(shí)例,那調(diào)用的就是拷貝構(gòu)造函數(shù);如果沒(méi)有,那就是對(duì)已有的對(duì)象賦值,調(diào)用的是賦值運(yùn)算符。
調(diào)用拷貝構(gòu)造函數(shù)主要有以下場(chǎng)景: