ところで以前、コンストラクタで実行時メモリ確保を行い、デストラクタで破棄する手法をご紹介しましたよね。実はその手法には欠点があるのです。


コンストラクタでメモリを実行時に確保し、デストラクタで破棄しています。
このソースコードは一見正しく見えますが、実行すると例外が発生し、プログラムが落ちます。

2枚目のソースファイルを見て下さい。生成したEnemy1オブジェクトを関数へ渡していますね。
そうです。値渡しです。つまりこのオブジェクトEnemy1は、PowerUP関数へオブジェクトのコピーが渡され、returnする時に破棄され、ここでデストラクタが呼び出されます

その後、戻り値を戻す際にも一瞬オブジェクトのコピーが生成され、そこでもMPが指すメモリ上のアドレスが解放されます。同じアドレスを2回deleteするので、例外が発生するのです。
戻り値を戻す際になぜコピーが発生するかというと、戻り値の返却も値渡しだからです。
158

int* MP;はアドレス変数です。newで領域を確保し、その領域の場所をMPへ格納しているだけなので、MPをコピーしても新しく領域が確保される訳ではありません。値渡しの際に作成されるコピーも、戻り値を戻す際に一瞬作成されるコピーも、main関数で定義されたEnemy1オブジェクトも、全て同じ領域を指します。
なので、main関数が終了すると、更にデストラクタでメモリ上の領域を解放するのです。

この問題を解決する最も簡単な手法を次回、ご紹介致します。