1、拷貝構造函數:用一個已經有的對象構造一個新的對象。
CA(const CA & c )函數的名稱必須和類名稱相一致,它的唯一的一個參數是本類型的一個引用變量,該參數是const 類型,不可變。
?? 拷貝構造函數什么時候被用到?
(1)當用一個已初始化過的自定義類型對象去初始化另一個新構造的對象的時候。
(2)一個對象以值傳遞的方式傳入。在調用函數時需要將實參對象完整的傳遞給形參,系統是通過調用拷貝構造函數來實現的,這樣能保證形具有和實參完全相同的值。
(3)一個對象以值傳遞的方式傳出函數體。在函數調用完畢將返回值帶回函數調用處。此時需要將函數中的對象拷貝到一個臨時對象處并傳給該函數的調用處。
?拷貝構造函數為什么傳引用而不傳值?
如果拷貝構造函數進行值傳遞的話,那么形參會產生一個新對象,也就是會調用拷貝構造函數,因此會形成一個死循環。
調用拷貝構造函數需要先創建形參對象,創建形參對象又需要調用拷貝構造函數,無限遞歸肯定是不正確的,所以在這里要用引用而不是值傳遞。
?
2、賦值運算符的重載函數:用一個已經有的對象給一個同一類型的對象賦值。(兩個對象都存在)
CA & operator = (const? CA & )
返回值的對象為引用是為了可以連續賦值
賦值函數中可以既可以使用引用也可以使用值傳遞,不過值傳遞會多生成一個對象,造成資源的浪費。
class A
{
private:
?int a;
?int b;
public:
?A (const A & arg) // 拷貝構造函數 ?
?{
??a = arg.a;
??b = arg.b;
?}
?A & operator = ( const A & arg) //重載的賦值函數?
?{
??if(this != &arg)// 先判斷下是否是自身賦值
??{
???a = arg.a;
???b = arg.b;
??}
??return *this;
?}
};
當類中含有指針成員時,兩者的意義有很大區別
復制構造函數需為指針變量分配內存空間,并將實參的值拷貝到其中;而賦值操作符它實現的功能僅僅是將‘=’號右邊的值拷貝至左值,在左邊對象內存不足時,
先釋放然后再申請。當然賦值操作符必須檢測是否是自身賦值,若是則直接返回當前對象的引用而不進行賦值操作。
拷貝構造函數分為兩類:

深拷貝
class Student
{
private:
?char *name;
public:
?Student (const Student & arg)
?{
??int length = strlen(arg.name)+1;
??this->name = new char[length]; ? // 深拷貝,先在堆上分配內存,再拷貝內容。
??strncpy(this->name,arg.name,length);
?}
?Student & operator=( const Student &arg)
?{
??if(this != &arg)
??{
???delete []name;// 先銷毀之前分配的堆上的內存
??}
??int length = strlen(arg.name)+1;
??this->name = new char[length];// 重新分配,并拷貝。
??strncpy(this->name,arg.name,length);
??return *this;
?}
};
?