====== コピーコンストラクタをちゃんと書かないと駄目なパターン ======
==== cPosition.h ====
#pragma once
class cPosition
{
private:
int x, y;
public:
int* mem; //これを追加
//インライン関数定義
void setX(int _x) { x = _x; }
void setY(int _y) { y = _y; }
int getX() const { return(x); }
int getY() const { return(y); }
cPosition();
cPosition(int _x, int _y);
//コピーコンストラクタは宣言しない=デフォルトのコピーコンストラクタが呼ばれる
//デフォルトのコピーコンストラクタの動作は、とにかく全メンバコピー
void printPosition();
};
==== cPosition.cpp ====
#include "cPosition.h"
#include
using std::cout;
using std::endl;
cPosition::cPosition()
:x(0),y(0),mem(nullptr) //ポインタをnullptrで初期化
{
cout << "引数なしのコンストラクタ" << endl;
}
cPosition::cPosition(int _x, int _y)
:x(_x),y(_y), mem(nullptr) //ポインタをnullptrで初期化
{
cout << "引数付きコンストラクタ" << endl;
}
void cPosition::printPosition()
{
cout << "(" << this->x
<< ", " << this->y
<< ")" <mem) << endl;
//memの中身(値)を表示
}
==== theMain.cpp ====
#include "cPosition.h"
#include
int main()
{
//引数付きコンストラクタが呼ばれる
cPosition p1(3, 4);
int var = 5;
p1.mem = &var; //変数varのアドレスをmemに代入
//引数なし(デフォルトコンストラクタ)
cPosition p2;
//デフォルトコピーコンストラクタが呼ばれる
cPosition p3 = p1;
p1.printPosition();
p2.printPosition();
p3.printPosition();
}
===== コピーコンストラクタの動きを確認してみる =====
#include "cPosition.h"
#include
int main()
{
//引数付きコンストラクタが呼ばれる
cPosition p1(3, 4);
int var = 5;
p1.mem = &var; //変数varのアドレスをmemに代入
//引数なし(デフォルトコンストラクタ)
cPosition p2;
//デフォルトコピーコンストラクタが呼ばれる
cPosition p3 = p1;
p1.printPosition();
p2.printPosition();
p3.printPosition();
}
これで結果を表示すると、\\
int var = 5;\\
__のアドレスが、p1.memに代入されているため *(p1.mem) は 5 になる。__\\
(これはもうそろそろわかってほしい。。。)\\
そのうえで、デフォルトのコピーコンストラクタが動くので(メンバ全コピーなので)\\
cPosition p3 = p1;により\\
p1.memの指すアドレス(= &var)とp3.memの指すアドレスは同じものになる。\\
(p3.mem = &var; を書いたのと同じ結果になる。)\\
動的にとったメモリがある場合は、
* そのコピー元のメモリをコピー先と共有する
* コピー元のメモリ状態(配列やクラスが動的に確保されている状態)がコピー先に再現され、そこに値がコピーされる
どちらが望む動作なのか考えないとだめだよ。
参考ページ:\\
https://monozukuri-c.com/langcpp-copyconstructor/ \\
http://yohshiy.blog.fc2.com/blog-entry-303.html \\