あるクラスで確保した領域を別のクラスで開放するには?

[戻る]
なおじー 2005/01/20(木) 09:17:00
はじめまして。
現在、あるクラスのモジュール内で別のクラス内で確保された領域を開放させる処理を
入れようと思っているのですが上手くいかず困っています。
内容は以下の通りです。
●ヘッダー定義内容
class A
{
public:
    UCHAR*   m_pB;              // 取得領域へのポインタ
    void     C(void);           // 領域を確保する処理があるモジュール
};
●void C(void)のモジュール内
    *m_pB = new UCHAR[・・・];  // 領域確保
●開放処理を行いたいクラスのモジュール
void CSubDlg::OnClose()
{
//>>> ?
}
このような場合、OnClose()内でC(void)で確保した領域を開放するには"?"の部分にど
のように記述すればよいのでしょうか?よろしくお願いします。

επιστημη 2005/01/20(木) 09:28:53
void CSubDlg::OnClose() {
  ...
  delete 開放したい領域を持ったオブジェクト.m_pB;
}

なおじー 2005/01/20(木) 09:36:39
επιστημηさん。ありがとうございます。

”開放したい領域を持ったオブジェクト”とあるのですが、具体的にどのように定義す
ればよいのでしょうか?
よろしくお願いします。

Takahashi 2005/01/20(木) 09:52:47
メモリ確保のメンバ関数があるので解放するメンバ関数を作った方がいいのでは?
例えばこんなメンバ関数

void A::Delete()
{
  if(m_pB != NULL){
    delete m_pB;
    m_pB = NULL;
  }
}

void CSubDlg::OnClose()
{
  開放したい領域を持ったオブジェクト.Delete();
}

この方が私的には好みです。
# m_pB は private にしてカプセル化した方がいいと思います。

あと、class A が CSubDlg のメンバならば class A のデストラクタで delete すれば
ダイアログの終了で勝手に delete してくれます。

# 開放したい領域を持ったオブジェクト ってのはこれでわかりますよね?

NowNow 2005/01/20(木) 09:54:58
AクラスをCSubDlgのメンバー変数として持っているなら...

//クラス定義
class A
{
public:
    UCHAR*   m_pB;              // 取得領域へのポインタ
    void     C(void);           // 領域を確保する処理があるモジュール
};

//SubDlgクラス
class CSubDlg
{
    ...
    A m_A;
    void OnClose():
    ...
};

void CSubDlg::OnClose()
{
  ...
  delete m_A.m_pB;
}

こんな感じでいいのでは?
ただし、m_A.m_pBの指すポインタにちゃんとメモリー確保されているかどうかのチェック
機構を入れないと、変なポインタをdeleteする結果になるかもしれません。

NowNow 2005/01/20(木) 09:57:09
>    void OnClose():

「:」 -> 「;」のミスです。すみません。
    void OnClose();

なおじー 2005/01/20(木) 10:01:33
Takahashi さん。ありがとうございます。

Takahashi さんのサンプルソースだとイメージ的にはCSubDlg::OnClose()で開放処理を
入れるのではなく、CSubDlg::OnClose()でクラスAで定義したDelete()モジュールを呼び
出すということですよね?
参考になりました。早速やってみたいと思います。また結果報告します。

なおじー 2005/01/20(木) 10:05:41
NowNow さんありがとうございます。

ちなみにclass A は CSubDlg のメンバになっていますので早速やってみます。

Takahashi 2005/01/20(木) 10:56:29
より完璧にしたいのならば私はこう書きます

class A
{
    UCHAR*   m_pB;              // 取得領域へのポインタ

public:
    A() : m_pB() {}
    ~A() { Delete(); }

    void    C(void);           // 領域を確保する処理があるモジュール
    void    Delete();          // さっきの解放する関数
};

これでリークする可能性はかなり減りますが、オブジェクトのコピーを考慮しなければな
りません。
例えばこんなコピーコンストラクタが必要です

A(const A& a)
{
  if(a.m_pB != NULL){
    // 新しい領域を確保して、a.m_pB をコピーする
  }
}

コピーする必要がないのならばコピーコンストラクタを殺さないと(呼び出せなくする)メ
モリリークする可能性があります。
# 理由はわかりますよね?
結構めんどっちいので、UCHAR が単に文字列とかであれば CString とか std::string 等
を使用するか、コンテナ等利用できないか検討した方が楽です。

なおじー 2005/01/20(木) 10:59:58
επιστημηさん 、Takahashi さん、NowNow さんありがとうございました。
無事領域開放することができました。

後、聞いておきたいことがあるのですが、VC++でデバッグ終了時、メモリリークが
あるとその内容がアウトプットに表示されるのですが、ここは該当データがちゃんと全
て表示されているのでしょうか?よろしくお願いします。

古いスレッドには追加発言できません。