2

私はこのC++クラスを持っています:

class test{

    char* p;
    SomeClass* someObject;

   test(){
      ...
      p = (char*) malloc(1000);
      someObject = new SomeClass();
      ...
   }

   ~test(){}

}

free(p)割り当てられたメモリを解放するためにテスト デストラクタで明示的にorを呼び出す必要がありdelete someObjectますか? またはそのメモリは自動的に解放されますか?

4

5 に答える 5

8

デストラクタで動的に割り当てられたすべてのメモリを解放する必要があります。これは自動的には行われません。

クラスには 2 つのポインターが含まれており、基本的にこれらが何を指しているかを制御することはできません。実際、これらは削除が許可されていないオブジェクトを指している可能性があります。次に例を示します。

struct Foo {};
struct Bar {
  Foo* f_;
  Foo(Foo* f) : f(f_) {}
};

int main() {
  Foo f;
  Bas b(&f); // b has a Foo ptr, but should it delete it?
}

したがって、ポインター データ メンバーが自動的に削除されるのはあまり意味がないことがわかります。

原則として、クラスがリソースを管理する場合は1、コピーの作成と割り当てに注意する必要があります。つまり、クラスにとって意味がある場合はそれらを無効にするか、コンパイラが生成したものは機能しないため、それらの実装を提供する必要があります。このトピックに関する詳細な議論については、3 つのルールと、stackoverflow に関する広範な議論を参照してください。

この規則に従わない場合、デフォルトのコピー コンストラクターと代入操作によって浅いコピーが作成され、同じ動的に割り当てられたオブジェクトへのポインターを持つ複数のインスタンスが作成され、それらはすべて破棄時に削除されます。

スマート ポインタnewを使用して、で作成されたオブジェクトを手動で削除することを回避できます。クラスが明らかに動的に割り当てられたオブジェクトを所有している場合、C++ 11 のstd::unique_ptrまたはboost::scoped_ptrを確認する必要があります。

最後に、本当に必要な場合を除き、ポインターをすべて一緒に回避することで、すべてのメモリ管理の問題を実際に回避できます。たとえばchar*、次のように置き換えることができます。std::string

class test{

    std::string p;
    SomeClass someObject;
    //test() : someObject() {} // default construction is probably OK...
};

1. つまり、メモリの割り当てと割り当て解除、ネットワーク接続の開閉、ミューテックスの作成と破棄などを行います。

于 2012-07-02T05:54:55.823 に答える
3

はい、あなたはfree何でもしなければmallocなりdeleteませんnew

クラスにポインターを格納しないことで、これを回避することもできます。

class test{
public:
    std::string   p;
    SomeClass     someObject;
};
于 2012-07-02T06:07:06.093 に答える
1

はい、必要です。したくない場合は、スマート ポインターを使用できます。

于 2012-07-02T05:57:17.397 に答える
0

testのインスタンスが破棄されたときにメモリを再利用しないと、技術的にメモリがリークされます。free代わりにスマート ポインターを使用して、デストラクタでorをdelete明示的に呼び出すことを回避できます。

struct Free { void operator () (void *p) const { free(p); } };

class test {
    std::unique_ptr<char, Free> p;
    std::unique_ptr<SomeClass> someObject;
    test () : p(static_cast<char *>(malloc(1000)),
              someObject(new SomeClass)
    { //...
    }
    ~test () {}
};

これは、スマート ポインターのデストラクタを使用してクリーンアップ アクションを実行します。

testグローバルインスタンスとしてのみ使用された場合const、実行が終了するまでメモリが再利用されないため、クリーンアップを実装することはそれほど重要ではありません。ただし、常にクリーンアップを実装することをお勧めします。これにより、コードが正しくなりtest、将来別の方法で使用される可能性があるためです。

于 2012-07-02T06:07:38.833 に答える
0

はい、明示的に解放する必要があります。データ型としてのポインタにはデストラクタがありません。コンパイラ/実行環境には、ポインタが意味のあるものを指しているかどうかを推測する手段がありません。値が意味のあるものであっても、たとえば静的オブジェクトを指している場合があります。または、より大きなオブジェクトのフィールドを指すこともできます。コンパイラは、ポインターの自動クリーンアップを行っていません。

于 2012-07-02T05:55:51.487 に答える