0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

M5Stack C++学習 クラスインスタンスをコピー

0
Last updated at Posted at 2024-02-22

クラスインスタンスをコピーする。

<確認したい内容>
1.クラスインスタンスをコピーする場合、新たに領域を確保してコピーしているのか, 確認する。

2.代入演算子=のオーバーロードで、きちんとコピーできるか。

3.コピーコンストラクタが起動する場合と、代入演算子=が使用される場合、その用途の違いを確かめる。

そもそも、コピーという言葉があいまいで、どう具体的にコピーされているのか、実コードで確認する。

C++のコピーには、2種類の定義があります。
ディープコピーDeep Copy: 実体を、新たな領域を確保してコピー。
シャローコピーShallow Copy: ポインタ同士の、コピー。

コピーコンストラクタ構文

constructor.cpp
class class_A
{
    public:
        class_A(const class_A& existedOtherClass);
};

定義は決まっているので、引数に同じクラスを割り当てると起動します。

事前定義識別子 __PRETTY_FUNCTION__
名前空間名、クラス名、戻り値やパラメータといった情報も含む関数の文字列。
デバッグなどで、実行された関数名を表示したいときに使用します。

クラスインスタンスのコピーを行うときは、メンバー変数に外部本体をもつポインターがあるか、確認しておきます。
コピーしたときに、ポインタが保持しているアドレスはコピーされますが、2つのクラスインスタンスが、一つの実態しかないオブジェクトを、不意に共有してしまう可能性があります。デストラクタの、2重解放もありえます。
コンパイラの自動生成したコピーコンストラクタを使うときは、注意が必要です。

クラスインスタンスのコピー 動作確認コード

__PRETTY__FUNCTION__を使用して、どのメソッドが、どの順番で、起動したか、
確認できるようにしています。

1.CLクラスインスタンスCL1の生成

2.CLクラスインスタンスCL2CL1のコピーコンストラクタで生成。
  ※CL1CL2のアドレスが違うことを確認。

3.CL2のメンバー変数を変更し、CL1に変化がないことを確認。

4.CLクラスインスタンスCL3を代入演算子=を使用して、コピーコンストラクタで生成。
  ※このとき、代入演算子=のオーバーロードで生成されていないことを確認。

5.CLクラスインスタンスCL4をCLクラスコンストラクタで生成。

6.代入演算子=をつかってCL4CL1を代入。コピーされているか確認。
  ※このとき、代入演算子=のオーバーロードが使用されているか、確認。

7.setupを抜けると各インスタンスのデストラクタが起動。その順番を確認。

main.cpp
#include <M5Core2.h>

/**
 * コピーコンストラクタ
 * ディープコピー
 * 事前定義識別子
*/

class CL
{
  public:
    //コンストラクタ
    CL(String s, int n)
    { Serial.printf("%s\r",__PRETTY_FUNCTION__);  name=s; num=n; }
    //デストラクタ
    ~CL(){Serial.printf("%s %x\r ",__PRETTY_FUNCTION__, this);}
    //コピーコンストラクタ
    CL(const CL& _cl)
    { Serial.printf("%s\r",__PRETTY_FUNCTION__); num=_cl.num; name=_cl.name;}
    //代入演算子=オーバーロード
    CL& operator=(const CL& _cl)
    { Serial.printf("%s\n",__PRETTY_FUNCTION__); num=_cl.num; name=_cl.name; return *this;};
    //メンバ変数の表示
    void print(String s){Serial.printf("%s Add:%x name:%s,num:%d\r", s, this, name, num);}
  public:
    String name;
    int num;    
};

void setup()
{
    M5.begin();
    Serial.print("------CL1 Construction-------\r");
    CL CL1("CL1",1);
    CL1.print("CL1");
    Serial.print("------CL2 Copy Construction-------\r");
    CL CL2(CL1);
    CL1.print("CL1");
    CL2.print("CL2");
    Serial.print("------Change CL2 values-------\r");
    CL2.name="CL2";
    CL2.num=2;
    CL1.print("CL1");
    CL2.print("CL2");
    Serial.print("------Initial Copy CL3=CL1 ----------\r");
    CL CL3 = CL1;
    CL1.print("CL1");
    CL2.print("CL2");
    CL3.print("CL3");
    Serial.print("------CL4 Construction ----------\r");
    CL CL4("CL4",4);
    CL4.print("CL4");
    Serial.print("------CL4 = CL1 ----------\r");
    CL4 = CL1;
    CL1.print("CL1");
    CL4.print("CL4");
    Serial.print("------Close destruction ----------\r");
}

void loop()
{
   delay(1);
}

シリアルに出力した、実行結果
コピーコンストラクタ結果.png

今回は、ディープコピーで、実体を2つに増やすことをメインに検証しました。
インスタンスコピーに関して、理解の解像度が上がったと思います。

<参照サイト>

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?