拷貝構造函數、拷貝賦值函數——C++篇

一、拷貝賦值函數與拷貝構造函數

拷貝賦值函數和拷貝構造函數,都是通過已存在的一個類對象對另外一個類對象進行初始化的操作,但兩者有着本質上的區別:

  • 拷貝賦值函數:針對一個已經存在的對象進行初始化操作。
  • 拷貝構造函數:針對一個新創建的對象進行初始化操作。
Plane a1;
//拷貝構造
Plane a2 = a1;
Plane a3;
//拷貝賦值
a2 = a3;

二、拷貝構造函數

拷貝構造函數,又稱複製構造函數,它可以生成一個當前對象的副本,然後將其的參數成員逐個拷貝到正在創建的本類對象中。

class Plane{
  public:
    Plane(int height,int width){
      height = 10;
      width = 20;
    }
    //聲明拷貝構造函數
    Plane(const Plane &a);
    int getH(){return height;}
    int getW(){return width;}
  private:
    int height;
    int width;
};

//定義拷貝構造函數
Plane::Plane(Plane &a){
  height = a.height;
  width = a.width;
}

在C++中,拷貝構造函數的有三種情況會被調用。

  1. 一個對象用於給另外一個對象進行初始化(常稱爲賦值初始化)。
Plane a1(15,25);
Plane a2(a1);
  1. 一個對象作爲函數返回值,以值傳遞的方式從函數返回;
Plane fun1(){
  Plane a1(15,25);
  return a1;
}

int mian(){
  Plane a2;
  a2 = fun1();
}
  1. 一個對象作爲函數參數,以值傳遞的方式傳入函數體;
void fun2(Plane a){
  //具體代碼
}

int main(){
  Plane a1(15,25);
  fun2(a1);
}

值得注意的是,在後兩種情況下如果不使用拷貝構造函數,就會導致指針指向一個已經被刪除的內存空間。

三、淺拷貝、深拷貝

淺拷貝和深拷貝都屬於拷貝構造函數。

  1. 淺拷貝:在拷貝的同時增加一個指針,但是通過淺拷貝的對象和原有對象共用同一個內存地址,當對象被修改時,通過淺拷貝的對象均被修改;如果對象調用析構函數時,則會出現同一資源被多次釋放的錯誤。
class Plane{
  public:
    Plane(int height,int width){
      height = 10;
      width = 20;
    }
    int getH(int h){return height;}
    int getW(int w){return width;}
    int changeH(int h){return height = h;}
    int changeW(int w){return width = w;}
  private:
    int height;
    int width;
};

int main(){
  Plane a1(15,25);
  Plane a2(a1);
  a1.changeH(30);
  //此時a1和a2的height的值都是30
  cout<<a1.getH()<<a2.getH()<<endl;
}

  1. 深拷貝:在拷貝的同時增加一個指針,並重新申請一塊新的內存空間,使得該指針指向新申請的內存空間。使用深拷貝後能夠避免出現淺拷貝中的錯誤情況。
class Plane{
 public:
   Plane(int height,int width){
     height = 10;
     width = 20;
   }
   int getH(int h){return height;}
   int getW(int w){return width;}
   int changeH(int h){return height = h;}
   int changeW(int w){return width = w;}
 private:
   int height;
   int width;
};

int main(){
 Plane a1(15,25);
 Plane a2(a1);
 a1.changeH(30);
 //此時a1的height值是30,而a2的height值則不變
 cout<<a1.getH()<<a2.getH()<<endl;
}

四、使用的注意事項

  • 拷貝構造函數必須以引用的形式進行傳遞
    如果拷貝構造函數進行值傳遞的話,首先會將實參傳遞給形參,此時系統又會默認調用拷貝構造函數,這樣就會不斷進行遞歸調用,從而陷入死循環。
  • 拷貝構造函數最好使用const關鍵字
    拷貝構造函數的目的是對對象進行成員複製,而不是修改原對象,爲了避免複製過程中發生對原對象的修改,應該使用const關鍵字。
Plane(const Plane &p);
總結不易,如有不足,懇請指導!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章