4

これは、最も基本的な用途を除いて C++ で使用newしたことがないため、単なる好奇心のためです。delete

私はそれdeleteがメモリを解放することを知っています。私が疑問に思っているのは、より複雑なケースをどのように処理するのですか?

たとえば、次のようなユーザー定義クラスがあるとします。

class MyClass
{
public:
    MyClass();
    ~MyClass()
    {
        delete [] intArray;
    }
    //public members here
private:
    int* intArray;
};

クラスが何らかの方法でメモリを割り当てintArray、デストラクタで解放すると仮定すると、次のようにクラスを使用した場合MyClass* myClass = new MyClass();:delete myclass;

deleteすべてのメモリの解放をどのように処理しますか? クラス デストラクタは、最初に呼び出されて、クラスによって割り当てられたすべてのメモリを解放し (つまりint* intArray)、クラスを保持するために割り当てられたメモリを解放しますか?

次のようなクラスがあるとしたらどうでしょうか。

class MyClass
{
public:
    MyClass();
    ~MyClass()
    {
        delete anotherMyClass;
    }
    //public members here
private:
    MyClass* anotherMyClass;
};

がコンストラクターで割り当てられていないと仮定するとanotherMyClass、メモリをすぐに使い果たしてしまいます。連結リストのように互いに関連付けられた MyClasses のチェーンがあった場合はどうなるでしょうか? この場合、デストラクタの削除ステートメントは機能しますか? デストラクタが呼び出されると、それぞれanotherMyClassが再帰的に解放されますか?

あなたが知っているnewandステートメントに関する特定の奇妙なトリックや警告はありますか?delete

4

2 に答える 2

10

p動的に割り当てられたオブジェクトへのポインター ( ) を指定すると、次のdelete2 つのことが行われます。

  1. 動的に割り当てられたオブジェクトのデストラクタを呼び出します。~MyClass()完了すると、クラス型のメンバー変数のデストラクタが呼び出されることに注意してください。
  2. 動的に割り当てられたオブジェクトが占有していたメモリを解放します。

解放する他のポインターのオブジェクトのメンバー変数を検索しません。他のメモリを解放せず、他に何もしません。

が指すメモリを解放する必要があるintArray場合deleteは、 のデストラクタで解放する必要がありますMyClass

ただし、ほとんどすべての C++ コードでは、これについて心配する必要はありません。shared_ptr、、、、などのスマート ポインターを使用して、動的に割り当てられたオブジェクトを自動的に管理する必要がunique_ptrありますauto_ptrscoped_ptr手作業によるリソース管理は、良くても困難であり、可能な限り避けるべきです。

これは、より広いイディオム、Scope-Bound Resource Management (SBRM、Resource Acquisition is Initialization、または RAII とも呼ばれます) の一部です。これは、理解して C++ コードのあらゆる場所で使用する最も重要な設計パターンです。

クラスで代わりにこれを宣言した場合:

boost::scoped_ptr<int> intArray;

scoped_ptr<int>オブジェクトが破棄されると、保持しているポインタが解放されます。その後、オブジェクトを手動で破棄する作業を行う必要はありません。

適切に作成された最新の C++ コードでは、手動で を使用する必要はほとんどありませんdelete。動的に割り当てられたオブジェクトを含め、クリーンアップが必要なあらゆる種類のリソースを管理するには、スマート ポインターとその他の SBRM コンテナーを使用する必要があります。


2 番目の例では、次のようなリンク リストが与えられます。

x -> y -> z -> 0

次のような操作の順序があります。

delete x;
  x.~MyClass();
    delete y;
      y.~MyClass();
        delete z;
          z.~MyClass();
            delete 0;
          [free memory occupied by z]
      [free memory occupied by y]
  [free memory occupied by x]

リンクされたリスト内のオブジェクトは、逆の順序で破棄されます。

于 2010-11-23T21:14:41.800 に答える
1
delete intArray;

intArray配列の最初の要素を指していると思いintますか?その場合、delete intArray未定義の動作が発生します。経由で割り当てた場合は、経由で解放new[]する必要delete[]があります。

delete[] intArray;

はい、特定のコンパイラ オプションの下で特定のコンパイラ バージョンを使用する特定のシステムで問題なく動作するように見えるdelete intArray場合も あれば、そうでない場合もあります。それはあなたにとって未定義の動作です。

また、 3 つのルールに従う必要があります。独自のデストラクタを定義するが、暗黙的に定義されたコピー コンストラクタとコピー代入演算子に依存することは、災害のレシピです。

于 2010-11-23T21:39:23.093 に答える