モードレスダイアログをnewで表示させるけど、どこでdeleteするのか？


MFCのダイアログベースでプロジェクトを作り、そのダイアログでボタン押下するとサブのダイアログをモードレスで表示する機能があったとします。  
newでサブダイアログをインスタンス化するのですが、どこでdeleteすればいいのかわからず質問させていただきました。  
ボタン押下イベントのなかでnewしてdeleteするとサブダイアログは消えてしまいます。

[code]

    void CModelessDlgTestDlg::OnBnClickedButton1()
    {
        ModelessDlg* dlg = new ModelessDlg(this);
        dlg->Create(IDD_MODELESSDLG, this);
        dlg->ShowWindow(SW_SHOW);
    
        delete dlg; //ここでサブダイアログが消えてしまう。かといってdeleteしない？のはダメでしょ＾＾；
    }
    
    
[/code]

かと言って、コンストラクタでnewしておいて、デストラクタでdeleteするとしたら、複数のサブダイアログが開かれたときにメモリが足りなくなるのでは・・・  
（まぁいまのコンピュータからすれば幾多のダイアログ開かないとメモリが飛ぶことはないのでしょうが）

この場合、どこでdeleteすればいいのかわからないのでご教授いただけないでしょうか。




私ならこうします。

モードレスのダイアログといえども、閉じる操作があるはずです。そのダイアログに閉じるボタンがあるとか。  
そのボタンのアクションの中で delete this; と書きます。

delete thisを使うからには、それ以後メンバ変数を触ってはいけません。

サブダイアログを閉じないうちに、アプリケーション自体を閉じたときに問題あるかないかは、調べてみないと分かりません。

（いまからMFCですか。ご苦労様です。）




既に回答がありますが、サブダイアログは１つという前提での回答になっています。そのためいずれも質問文の

> 複数のサブダイアログが開かれたとき

この部分に対応できていないように見受けられます。例えばExplorerでファイルごとにプロパティダイアログを開く、その際のプロパティダイアログの管理方法をイメージしました。

これに関して、MFCは機能不足で支援できていないようです。  
まず、ダイアログクラス（`CDialog`）はコピーが禁止されています。ダイアログオブジェクトを考えたとき、コピーによってダイアログが増殖するべきでもないため、当然の対応です。  
[C++11ではムーブセマンティクス](https://cpprefjp.github.io/lang/cpp11/rvalue_ref_and_move_semantics.html)といって移動の概念が導入されましたが、MFCはそれ以前の時代のライブラリであり、ムーブセマンティクスに対応していません。  
また、MFCでは`CArray`クラスにより配列機能を提供していますが、当然ながらムーブセマンティクスに対応していないため、ダイアログオブジェクトを格納することができません。  
過去のセオリーだと、`CArray<ModelessDlg*>`クラスでポインターの管理のみを行われていたように思います。当然ポインターですので、`new`
/ `delete` は開発者が管理責任を負います。

* * *

一応、（MFCではなく）C++言語側にこれを支援する機能が提供されています。  
[`std::list`](https://ja.cppreference.com/w/cpp/container/list)であれば、ダイアログクラスのようなコピーも移動もできないクラスを扱えます。楽をするためにコンパイルオプション[`/std:c++17`](https://docs.microsoft.com/ja-
jp/cpp/build/reference/std-specify-language-standard-
version?view=vs-2019)を付けると次のように書けます。

[code]

    class CModelessDlgTestDlg {
        ...;
        std::list<ModelessDlg> dialogs;
    };
    
    void CModelessDlgTestDlg::OnBnClickedButton1() {
        auto dlg = dialogs.emplace_back(this);
        dlg.Create(IDD_MODELESSDLG, this);
        dlg.ShowWindow(SW_SHOW);
    }
    
[/code]

説明すると、[`std::list::emplace_back()`](https://ja.cppreference.com/w/cpp/container/list/emplace_back)はリスト内部で指定された引数でコンストラクターを呼び出します。またC++17以降では作成されたオブジェクトの参照を返してくれます。  
リスト内部で生成されたオブジェクトなので、リストが責任を持って管理をします。具体的にはリストが破棄されるタイミングで、全メンバーのデストラクターを呼び出してくれます。

ただし、MFC利用者はC++言語機能を極端に嫌う傾向があり、この方法が受け入れられるかはちょっとわかりません。

