8

簡単な質問です。私はグーグルで調べて、すでにいくつかの答えを見つけましたが、私は少し偏執的であるため、確認したいと思います.

次の状況を考慮してください。

struct CoordLocation
{
    float X;
    float Y;
    float Z;
};

int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

delete を呼び出すと、フィールド X、Y、Z で使用されているメモリもクリアされますか? 私が見つけたいくつかの回答は、この方法で実際に参照されているオブジェクトではなく、 POINTER を削除するだけだと述べています。仮に...

struct CoordLocation
{
    float *X;
    float *Y;
    float *Z;
};

int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

構造体のコンストラクタ/デストラクタ内の各オブジェクトのメモリを手動で解放するとどうなりますか?

struct CoordLocation
{
    CoordLocation()
    {
         *X = new float;
         *Y = new float;
         *Z = new float;
    }
    ~CoordLocation()
    {
         delete X; delete Y; delete Z;
    }
    float *X;
    float *Y;
    float *Z;
};

int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

次のような単純な状況であることに気付きました。

   float *a = new float;
   *a = 5.0f;
   printf("%f", *a);
   delete a;
   printf("%f", &a);

printf は 5.0 を出力するため、a が指す変数は正確には破棄されません。

したがって、私の質問は次のとおりです。この場合、構造体で使用されているすべてのメモリを確実に解放するにはどうすればよいですか (メモリ リークがないように)。

struct CoordLocation
{
    float X;
    float Y;
    float Z;
};

int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

ありがとう!

4

3 に答える 3

22

deleteで割り当てるメモリのみが必要ですnew

printf は 5.0 を出力するため、a が指す変数は正確には破棄されません。

あなたは実際に未定義の動作に遭遇しています。値はまだ残っていますが、メモリは解放されており、再利用できます。

したがって、次のようになります。

struct CoordLocation
{
    float X;
    float Y;
    float Z;
};

デストラクタを省略しても、メモリ リークは発生しません。

次のスニペット:

struct CoordLocation
{
    float *X;
    float *Y;
    float *Z;
};

int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

メモリ リークが発生する可能性がありますが、そのままではありません。次のようになります。

int main()
{
    CoordLocation *coord = new CoordLocation();
    coord->X = new float();
    delete coord;
    return 0;
}

あなたの3番目の例

struct CoordLocation
{
    CoordLocation()
    {
         *X = new float;
         *Y = new float;
         *Z = new float;
    }
    ~CoordLocation()
    {
         delete X; delete Y; delete Z;
    }
    float *X;
    float *Y;
    float *Z;
};

int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

割り当てたすべてのメモリを解放するため、メモリ リークは発生しません。デストラクタを省略したり、 を呼び出すのを忘れたりするとdelete coord;、メモリ リークが発生します。

経験則として、 a deletefor everynewと a delete[]for every を呼び出せnew[]ば安全です。

于 2012-04-20T20:13:47.390 に答える
0

ポインタ自体には自動保存期間が割り当てられており、そこから解放するものはありません。構造体はこれらの3つのフィールドであり、を呼び出すと解放されますdeletedeleteによって返されたものだけを呼び出しますnew

何かを割り当てるときは、それを保持するのに十分なメモリを割り当てます。これは、そのすべてのフィールドを保持するのに十分なメモリを意味します(実装固有のハウスキーピングメモリもありますが、心配する必要はありません)。削除すると、割り当てたのと同じ量のメモリが解放されます。

ただし、注意すべき点の1つは、次のような場合です(C ++では、このような型は作成しませんが、例は適切です)。

struct Foo {
    char *str;
};

Foo *f = new Foo();
f->str = new char[10];

delete f;

この場合、漏れがあります。を削除しますf。これは、単一のを保持するのに十分なメモリで構成されていますが、それが指すchar*ものchar*も動的に割り当てられています。だから、あなたもそれを解放する必要があります:

delete f->str;
delete f;

繰り返しになりますが、C ++では、おそらくこの方法で型を設計するのではなくstd::string、RAIIなどの型や原則を優先しますが、例は適切です。

于 2012-04-20T20:20:38.607 に答える
0

この例では:

struct CoordLocation
{
    float X;
    float Y;
    float Z;
};

int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

メモリが解放されます。そのコードにはリークはありません。構造体にポインターが含まれている例では、(例で行ったように) デストラクタでそれらを解放する限り、リークは発生しません。

このスニペットでは:

float *a = new float;
*a = 5.0f;
printf("%f", *a);
delete a;
printf("%f", &a);

ポインタはメモリアドレスを「解放済み」としてマークするだけで、その内容を変更しないため、の値はa削除後も同じままです。delete解放されたポインターへのアクセスは未定義の動作です。

于 2012-04-20T20:13:30.437 に答える