0

私の仲間が私に言った、私はこのコードでメモリリークがあります

Base
{
    public:
        vector<Foo*> fooes;
};

Derived : public Base
{
    public:

        Derived ( )
        {
            for ( int i = 0 ; i < 10 ; i++ )
            {
                    this.fooes.push_back ( new Foo() );
            }
        };

};

しかし、彼はとても忙しい人で、私を助けることができないので、私はあなたに尋ねます、メモリリークはどこにありますか?そして、どうすれば修正できますか?私が理解しているように、メモリリークは、によって作成されたオブジェクトを削除しないことですnew Foo()。したがって、にデストラクタを追加し、ベクトルBaseをクリアするだけですよね?fooes

Base
{
    public:
        vector<Foo*> fooes;
        ~Base ( )
        {
            this->fooes.clear();
        };

};

質問は:

  1. これは正しいメモリリーク修正ですか?

  2. のデストラクタBaseは、派生のデストラクタの前に呼び出されますか?

  3. fooes削除中にバーターは自動的に削除されますか、Baseそれともクラスのすべてのメンバーを手動で削除する必要がありますか?

4

3 に答える 3

7

1)これは正しいメモリリーク修正ですか?

いいえ、要素を繰り返し処理して手動で行う必要deleteがあります。

2)Baseのデストラクタは、Derivedのデストラクタの前に呼び出されますか?

いいえ(オブジェクトを削除していると仮定しますDerived)。

3)Baseの削除中にfooesベクトルが自動的に削除されますか、それともクラスのすべてのメンバーを手動で削除する必要がありますか?

はい・いいえ。ベクトル自体は自動的に管理されるため削除されますが、そのメンバーは次のことを行いません。

~Base ( )
{
   for ( size_t i = 0 ; i < fooes.size() ; i++ )
     delete fooes[i];
};

deleteそれぞれとdelete[]ごとにnewとが必要new[]です。

これらすべてに代わるより良い方法は、スマートポインターを使用することです。

于 2012-09-03T10:29:46.983 に答える
3

ベクター内のすべてのポインターを繰り返し処理し、クリアする前にそれらを削除する必要があります。ベクトルはポインタをクリアしますが、自分で行うか、shared_ptrのようなものを使用するようにベクトルを変更しない限り、ポインタが指すメモリをクリアしません。ベクトルがオブジェクトのベクトルである場合、メモリリークは発生しませんが、要素はを介して割り当てられたポインタであるため、newそのメモリを解放する必要があります。ベクトルは自動的にそれを行いません。

于 2012-09-03T10:30:00.667 に答える
1

コード例にはメモリリークはなく、クラス定義だけです。プログラムがそのタイプのオブジェクトを作成してDerived破棄した場合、おそらく(以下を参照)メモリリークが発生します。ただし、プログラムがタイプのオブジェクトを作成し、保持しているDerivedすべてのオブジェクトを破棄してFooから元のオブジェクトを削除した場合、おそらくメモリリークは発生しません。

メモリリークを単独で分析できることはめったにありません。それらはプログラム全体のプロパティです。このクラスを変更してFooオブジェクトを削除することはできますが、意図しない新しい設計上の制約を課す可能性があります。たとえば、Fooオブジェクトは内部コンテナに登録され、そのようなオブジェクトはすべてプログラムが終了するまで存続する必要があります。その要件を考えると、のデストラクタ内のオブジェクトを削除するDerivedことは間違っています。

さて、それはすべて大部分が仮説です。Derived誰かがすべてのオブジェクトを削除するためにデストラクタを拡張することについて文句を言うことはありませんFoo-それはおそらく正しいことです。しかし、常に少し疑問があります...

于 2012-09-03T11:48:35.517 に答える