本文主要介紹了拷貝構(gòu)造函數(shù)和賦值運(yùn)算符的區(qū)別,以及在什么時候調(diào)用拷貝構(gòu)造函數(shù)、什么情況下調(diào)用賦值運(yùn)算符。最后,簡單的分析了下深拷貝和淺拷貝的問題。

拷貝構(gòu)造函數(shù)和賦值運(yùn)算符

在默認(rèn)情況下(用戶沒有定義,但是也沒有顯式的刪除),編譯器會自動的隱式生成一個拷貝構(gòu)造函數(shù)和賦值運(yùn)算符。但用戶可以使用delete來指定不生成拷貝構(gòu)造函數(shù)和賦值運(yùn)算符,這樣的對象就不能通過值傳遞,也不能進(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)算符的地方,會提示_無法調(diào)用該函數(shù),它是已刪除的函數(shù)_。
還有一點(diǎn)需要注意的是,拷貝構(gòu)造函數(shù)必須以引用的方式傳遞參數(shù)。這是因?yàn)?,在值傳遞的方式傳遞給一個函數(shù)的時候,會調(diào)用拷貝構(gòu)造函數(shù)生成函數(shù)的實(shí)參。如果拷貝構(gòu)造函數(shù)的參數(shù)仍然是以值的方式,就會無限循環(huán)的調(diào)用下去,直到函數(shù)的棧溢出。

何時調(diào)用

拷貝構(gòu)造函數(shù)和賦值運(yùn)算符的行為比較相似,都是將一個對象的值復(fù)制給另一個對象;但是其結(jié)果卻有些不同,拷貝構(gòu)造函數(shù)使用傳入對象的值生成一個新的對象的實(shí)例,而賦值運(yùn)算符是將對象的值復(fù)制給一個已經(jīng)存在的實(shí)例。這種區(qū)別從兩者的名字也可以很輕易的分辨出來,拷貝構(gòu)造函數(shù)也是一種構(gòu)造函數(shù),那么它的功能就是創(chuàng)建一個新的對象實(shí)例;賦值運(yùn)算符是執(zhí)行某種運(yùn)算,將一個對象的值復(fù)制給另一個對象(已經(jīng)存在的)。調(diào)用的是拷貝構(gòu)造函數(shù)還是賦值運(yùn)算符,主要是看是否有新的對象實(shí)例產(chǎn)生。如果產(chǎn)生了新的對象實(shí)例,那調(diào)用的就是拷貝構(gòu)造函數(shù);如果沒有,那就是對已有的對象賦值,調(diào)用的是賦值運(yùn)算符

調(diào)用拷貝構(gòu)造函數(shù)主要有以下場景: