【Cpp】ポインタを持っているクラスのコピーを作る際の注意(コピーコンストラクタ)

目次

クラス内でメモリを確保した際の注意

クラス内でポインタ変数で、新しく確保した(newした)配列を保持している場合、コピーコンストラクタを作成しておかないと、値渡しでクラスを複製した場合にデストラクタでメモリを開放したときに実行時エラーになります。

コピーコンストラクタを自分で実装していない場合は、自動的に生成されます。

仮引数が作られるときにもコンストラクタが呼ばれる

  • 仮引数 : 関数の引数に設定している変数のこと
    1
    2
    3
    4
    //  test = 仮引数
    void Show(Test test){
    // 処理
    }

メモリをコンストラクタで動的にメモリを確保しているクラスAを使う例

  • 引数は確保するメモリ量

初期化と、代入で呼ばれるメソッドが変わるので、最低コピーコンストラクタと代入演算子オーバーロードは作成する必要がある

1
2
3
4
5
A a(10);  //  コンストラクタが呼ばれる
A b = a; // コピーコンストラクタが呼ばれる
A c(5); // コンストラクタが呼ばれる

c = a; // 代入演算子が呼ばれる

コピーコンストラクタの基本構文

  • クラス名 : Test
    1
    Test(const Test& other);
1
2
3
Test::Test(const Test& other){
// otherのコピーを自分のメンバ変数に代入する
}

代入演算子オーバーロードの基本構文

  • 代入の場合は、すでにコンストラクタが呼ばれているので、コンストラクタで確保したメモリなどは開放してあげる必要がある場合がある

クラス名 : Test

1
void operator=(const Test& test);
  • 実装
    • 注意 : メンバ変数にポインタ型がある場合、イニシャライザでメモリを確保している場合は、メモリの開放とメモリの再確保が必要
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      void Test::operator=(const Test& other){
      // メモリの確保
      // get_array_size : 確保しているメモリサイズを返す
      int *array = new int[other.get_array_size()];

      // メモリの開放
      // m_array : ポインタ型
      delete[] m_array;

      ...
      }

【Cpp】ポインタを持っているクラスのコピーを作る際の注意(コピーコンストラクタ)

https://blog.djima.net/2021/09/30/【Cpp】ポインタを持っているクラスのコピーを作る際の注意-コピーコンストラクタ/

Author

Daiki Iijima

Posted on

2021-09-30

Updated on

2024-04-17

Licensed under