c++コピー構造関数(深いコピーと浅いコピー)

3540 ワード

通常のタイプのオブジェクトでは、int a=88などのコピーは簡単です.int b=a; 一方、クラスオブジェクトは通常のオブジェクトとは異なり、クラスオブジェクトの内部構造は一般的に複雑で、様々なメンバー変数が存在します.次に、クラスオブジェクトのコピーの簡単な例を示します.
#include <iostream>
using namespace std;

class CExample {
private:
     int a;
public:
     CExample(int b)
     { a=b;}
     void Show ()
     {
        cout<<a<<endl;
    }
};

int main()
{
     CExample A(100);
     CExample B=A;
     B.Show ();
     return 0;
} 

 
プログラムを実行し、画面出力100を実行します.以上のコードの実行結果から,システムはオブジェクトBにメモリを割り当て,オブジェクトAとのコピープロセスを完了していることが分かる.クラスオブジェクトの場合、同じタイプのクラスオブジェクトは、コンストラクション関数をコピーすることによってレプリケーションプロセス全体を完了します.次に、コピーコンストラクション関数の作業手順を例に挙げて説明します.
#include <iostream>
using namespace std;

class CExample {
private:
    int a;
public:
    CExample(int b)
    { a=b;}
    
    CExample(const CExample& C)
    {
        a=C.a;
    }
    void Show ()
    {
        cout<<a<<endl;
    }
};

int main()
{
    CExample A(100);
    CExample B=A;
    B.Show ();
    return 0;
} 

 
CExample(const CExample&C)は、カスタマイズされたコピーコンストラクション関数です.コピーコンストラクション関数は特殊なコンストラクション関数であり、関数の名前はクラス名と一致しなければならない.その唯一のパラメータはこのタイプの参照変数であり、このパラメータはconstタイプであり、可変ではない.たとえば,クラスXのコピー構造関数の形式はX(X&x)である.
コピーコンストラクション関数は、初期化されたカスタムクラスタイプオブジェクトで別の新しいコンストラクションオブジェクトを初期化すると自動的に呼び出されます.すなわち、クラスのオブジェクトをコピーする必要がある場合、コピーコンストラクション関数が呼び出されます.コピーコンストラクション関数は、1つのオブジェクトが関数体に値伝達され、1つのオブジェクトが値伝達されて関数から1つのオブジェクトに戻るには、別のオブジェクトで初期化する必要があります.
クラスにコピーコンストラクタが明示的に宣言されていない場合、コンパイラはオブジェクト間のビットコピーを完了するデフォルトのコピーコンストラクタを自動的に生成します.ビットコピーは浅いコピーとも呼ばれ、後述する.
カスタムコピーコンストラクタは、コンパイラがデフォルトのコピーコンストラクタを形成することを阻止し、ソースコードの効率を向上させる良いプログラミングスタイルです.浅いコピーと深いコピー
場合によっては、クラス内のメンバー変数は、ビットコピーを実行すると、A=Bなどのオブジェクトの値を完全にコピーするスタックメモリを動的に開く必要があります.このとき、Bのメンバー変数ポインタがメモリを申請している場合、Aのメンバー変数も同じメモリを指します.これは、Bがメモリを解放すると(例えば、解析)、A内のポインタが野ポインタになり、実行エラーが発生するという問題が発生します.
深いコピーと浅いコピーは、1つのクラスがリソースを持っている場合、このクラスのオブジェクトがコピープロセスが発生した場合、リソースが再割り当てされ、このプロセスが深いコピーであり、逆に、リソースが再割り当てされていない場合、浅いコピーであると簡単に理解できます.次に、深いコピーの例を挙げます.
#include <iostream>
using namespace std;
class CA
{
 public:
  CA(int b,char* cstr)
  {
   a=b;
   str=new char[b];
   strcpy(str,cstr);
  }
  CA(const CA& C)
  {
   a=C.a;
   str=new char[a]; //   
   if(str!=0)
    strcpy(str,C.str);
  }
  void Show()
  {
   cout<<str<<endl;
  }
  ~CA()
  {
   delete str;
  }
 private:
  int a;
  char *str;
};

int main()
{
 CA A(10,"Hello!");
 CA B=A;
 B.Show();
 return 0;
} 


深いコピーと浅いコピーの定義は、1つのクラスがリソース(スタック、または他のシステムリソース)を持っている場合、このクラスのオブジェクトにコピープロセスが発生した場合、このプロセスを深いコピーと呼ぶことができ、逆にオブジェクトにリソースが存在するが、コピープロセスがリソースをコピーしていない場合は浅いコピーと見なすことができると簡単に理解できます.
リソースを浅くコピーすると、リソースを解放するときにリソースの帰属が不明になり、プログラムの実行エラーが発生します.
Test(Test&c_t)はカスタムコピーコンストラクタであり、コピーコンストラクタの名前はクラス名と一致しなければならない.関数の形式パラメータはこのタイプの参照変数であり、参照でなければならない.
初期化済みのカスタムクラスタイプオブジェクトを使用して別の新しい構造のオブジェクトを初期化すると、コピーコンストラクタが自動的に呼び出され、カスタムコピーコンストラクタがない場合、デフォルトのコピーコンストラクタに提供されてこのプロセスを完了します.上のコードのレプリケーションコア文はTest(Test&c_t)コピーによるコンストラクタ内のp 1=c_t.p1;文が完了しました.