1

メイン関数では、new を使用してオブジェクトを作成し、それを削除しません。プロセスが終了すると、ヒープ領域がクリアされることを願っています。以下は、クラス A のオブジェクトがクラス B のメンバー変数であるサンプル コードです。クラス Bメンバー変数として multimap も持っています。

    Class A
    {
    Public:
    A(); //have definition in cpp file
    ~A();//have definition in cpp file
    Private:
    Int a;
    };

    Class B{
    Private:
    Std::multimap<string,string> map_test;
    Public:
    A a;
    B(); //have definition inn cpp file
    ~B();//does not have any definition in cpp file
    };

    int main()
    {
      B *b = new B();
      /* code section where it fills some 1000 key value pairs in the multimap 
         for some purpose */
      return 0;

    }

私の理解:

  1. ここでオブジェクトを削除しなくても、プロセスが終了するとヒープスペースが消去されるため、問題は発生しません。プログラムのスコープは上記のように制限されており、他の誰もこれを再利用することはありません。削除を使用しないのは良いことですか、悪いことですか? これについてあなたの提案は何ですか?
  2. オブジェクトのデフォルトのデストラクタを呼び出す必要があり、それが暗黙のマルチマップ デストラクタを呼び出します。したがって、マルチマップを明示的にクリアする必要はありません。間違っている場合は修正してください。
  3. 親クラスではデストラクタを宣言するだけで定義はありません。では、暗黙のデストラクタを呼び出すのか、それとも無視するのか? (定義しない理由はありません。理解を深めてください。)
  4. 親クラスの場合、暗黙のデストラクタを呼び出す場合、ここで定義されている子クラスのデストラクタを呼び出す必要がありますか?
  5. 親クラス オブジェクトは new を使用してインスタンス化されるため、ヒープ内に作成されます。次に、この親オブジェクトのメンバー変数が格納される正確な場所です。たとえば、オブジェクト "a" はメンバー変数であり、このメンバーの宣言を調べます。オブジェクト、スタックで作成されるようです。ここで、親オブジェクトとそのメンバーである子オブジェクトの正確なメモリ作成がどのように行われるかについて混乱しています。これを理解するのを手伝ってもらえますか?
4

4 に答える 4

1
  1. はい、オブジェクトがメインで作成されている限り。ただし、これを変更して、たとえば B の複数のインスタンスを作成したり、別のクラス内で使用したりする場合は、別の話です。また、valgrind のようなメモリ チェック ツールは、無視したくなるような新しい削除なしの誤検知を提供します。ただし、実際のメモリ リークが習慣になった場合は、それを無視することができます。

  2. 正解です。これが だった場合は、map<string, string*>クリーンアップが必要になる可能性があります。

  3. デフォルトのデストラクタを呼び出します

  4. はい、そうします

  5. 私は、基本クラスのメンバー変数が格納されている場所を尋ねていると思いますか? それらはヒープにも格納されます。これらは、メモリ内の派生クラス フィールドの前に配置されます。

于 2013-05-17T14:29:37.643 に答える
0
  1. ほとんどの OS は、プロセスの終了時にプロセスのヒープ領域をクリーンアップします。そうではない組み込み OS がたくさんあっても驚かないでしょう。さらに、メモリ リークが発生するため、これは依然として悪い習慣です。
  2. メモリをリークしているため、デストラクタは呼び出されません。とはいえ、デストラクタを実装しておらず、コンパイラが生成したデフォルトのデストラクタに依存している場合は、それを宣言するべきではありません。実際、リンカ エラーが発生していないことに驚いています。はい、マルチマップのデフォルトのデストラクタは、値のセマンティクスに対するコンテナの要件 (つまり、生のポインタがない) を守っている限り、マルチマップの内容を削除します。
  3. これは悪い習慣であり、プログラマーとして、リソースを常に適切に管理するようにする必要があります。また、ヒープを割り当てる理由がわかりませんb。スタック上にオブジェクトを作成するだけで、リソース管理について考える必要はありません。
  4. 宣言する場合は、デストラクタの宣言により、コンパイラによって生成されたデストラクタが暗黙的に無効になるため、実装を提供する必要があります。そのため、リンク エラーが発生しないことに驚いていると上で述べました。
  5. コンパイラは、階層をたどり、構築とは逆の順序でデストラクタを呼び出すことにより、基本クラスの破棄を処理します。
  6. いいえ、A と B の両方を含むオブジェクト全体がヒープ上に構築されます。そのため、B へのポインターを A へのポインターとしてエイリアスし、派生クラスを基底クラスであるかのように操作できます。
于 2013-05-17T14:33:07.210 に答える
0

事実 : C++ にはネイティブ (テーブルの下) のガベージ コレクションはありませんが、何らかのガベージ コレクションを強制できるものはたくさんあります。

したがって、コードでメモリ リークが発生します。B を割り当てたスコープの最後で、割り当てたメモリは _is not free'dです。

質問のリストに目を通す:

  1. いいえ、ポインターを削除しないと、メモリは解放されません。このトピックに関してできることがいくつかあります。

    • RAII イディオムを使用します(リソースの取得は初期化です)。つまり、オブジェクトを使用してメモリを管理します。
    • スマート ポインターを使用します。これらの構成要素は RAII (私の意見では最も一般的なのはstd::shared_ptrandstd::unique_ptrです) を強制し、それらが担当するメモリが正しく解放されるようにします。
  2. 場合によります。演算子を使用してオブジェクトを割り当てnew、それらをマップに挿入したが、他の場所で参照されていない場合は、マップのすべてのエントリを手動で削除する必要があります。マップ タイプはポインターではないため、この場合は適用されません。

  3. クラスは、デストラクタ宣言を省略することさえできます。それらが省略された場合、デストラクタ (コピー代入演算子、コピー コンストラクタ、デフォルト コンストラクタも含む) がコンパイラによって生成されます。

  4. 編集: member を宣言した場合、A a;明示的に削除する必要はありません。メンバーとして宣言するクラスでデストラクタが呼び出されると、そのデストラクタが呼び出されます。ただし、(コンストラクターなどで) 割り当てたポインターの場合は、デストラクターで削除する必要があります。

  5. オブジェクトに動的メモリ割り当てを使用すると、そのメンバーがどのように宣言されていても、オブジェクト全体がヒープ上にあります。

于 2013-05-17T14:38:52.817 に答える
0

あなたは多くの質問をしました。

最初に、プロセスが終了してすべてのメモリをクリアしても(そうであるように)alwsysがメモリをクリアすることをお勧めします。常にそれを処理します..shared_ptrを使用して簡単に行うことができます...

デストラクタは常に正しい順序で呼び出されますが、ポインターを格納する場合と同様にマルチマップ内の要素をクリアする必要があるため、マルチマップは危険です。深刻なリークが発生する可能性があります。

于 2013-05-17T14:24:17.170 に答える