2012-04-18 4 views
0

以下はすべて(すべての適切なデストラクタが呼び出され、すべてのメモリが解放されます)適切に破壊されますか?クラスの配列を削除する

Class** var = new Class*[50]; 
var[0] = new SubClass(); 

delete[] var; 

または私は配列を反復し、(I []はなかっ削除考えたものである)個々のオブジェクトを削除すべきであると同様に

Class* var[50]; 
var[0] = new SubClass(); 

delete[] *var; 

+3

'std :: vector >' –

+0

まず、コードは機能しますか? –

+0

@ Mr.TAMER:おそらく動作しているようです。しかし、これはまだ未定義の動作です。 –

答えて

0
Class* var[50]; 
var[0] = new SubClass(); 

delete[] *var; 

これは未定義の動作です。適切な方法は、あなたが、配列のすべての要素50のためのメモリを割り当てる場合は、あなたがそれらの一つ一つを反復処理し、削除する必要が

delete var[0]; //equivalent to delete *var; 

です。あなたはすべてのnew[]のために関連したdelete

  • を持っている必要があり、あなたが関連付けdelete[]
  • を持っている必要があり、すべてのnewため

    • deletedelete[]new[]newを混在させないでください。それをこのように考えて定義されていない動作につながるので、

    あなたの2番目のスニペットは不正ですC++。

    EDITあなたがはっきりと初心者であるため、これを少し解説しましょう。第二のスニペットもコンパイルされませんので、私は最初のものに集中するつもりです:

    Class* var[50]; 
    

    これはClassから50のポインタの配列を宣言します。ポインタがぶら下がっています - それらは初期化されておらず、Classオブジェクトは作成されません。

    var[0] = new SubClass(); 
    

    この​​オブジェクトのメモリを割り当て、配列内の最初のポインタを割り当てます。他のすべてのポインタは未初期化のままです。

    *var; 
    

    は、Class*である最初の要素を返します。これはvar[0]に相当します。

    delete[] *var; 
    

    試みはnewが割り当てられたClass*、上delete[]をコールするので、未定義の動作になります。

  • +0

    いいえ、適切な方法は、リソース管理クラスを使用することです。 – Puppy

    +0

    "あなたの2番目のスニペットは違法ですC++。"はい、私は右側に余分なものがあった(typo)=)。だから、2番目のものはループ+ delete []を必要とし、最初のものはループを必要とします。了解、ありがとう。 *編集* - > "2番目のスニペットはコンパイルされていないので"もう一度、私は** = Pにタイプミスがあります。それはコンパイルして実行する;)。 – nestharus

    +1

    @ user1136671:いいえ!この答えは悪いです!このようにしないでください。 – Puppy

    -2
    for(int i = 0; i < 50;i++)delete var[i]; 
    delete[] var; 
    
    +0

    -1を見てくださいこれは間違っています。割り当てようとしている要素よりも多くの要素を削除していますが、自動ストレージの配列でdeleteを呼び出すことはできません。 –

    0

    delete[]は、動的に割り当てられた配列です。 new []に相当します。 C++オープンスタンダードから

    抜粋(3.7.4.2)

    解放関数が例外をスローすることによって終了した場合、 動作は未定義です。 割り振り解除関数に供給される最初の引き数の値は、ヌルポインター値です。その場合、 割振り機能が標準ライブラリで提供されているものである場合、 呼び出しは無効です。それ以外の場合は、値は、オペレータ新しい(のstd :: size_t型)のいずれかの以前の呼び出しによって返された値 またはオペレータ新(STDのいずれかでなければならない標準ライブラリにオペレータ 削除(ボイド*)に供給されます。 : 標準ライブラリのサイズ_t、CONSTはstd :: & nothrow_t)標準 ライブラリに、オペレータに供給値削除[](ボイド*)のいずれかの前 呼び出しによって返される値のいずれかでなければなりません演算子new [](std :: size_t)または演算子 new [](std :: size_t、const std :: nothrow_t &)を標準ライブラリに追加します。

    あなたがdelete []を使用することを想定していないので、あなたの最初の例では、new []を使用していません!

    3

    適切な方法は、std::vector<std::unique_ptr<MyClass>>のようなリソース管理クラスを使用することです。これにより、ユーザーの介入なしにリソースのクリーンアップが常に保証されます。 delete,new[]またはが使用されるC++コードは、直ちにリファクタリングして回避する必要があります。newはもう一度見てください。

    +1

    コメントです。彼が提供したスニペットのメモリをクリアする正しい方法は 'delete'です。あなたは代替案を提供していますが、それは問題ありません。 –

    +1

    @ルチアン:記憶を扱う適切な方法は、クラスを通してです。 OPが何か恐ろしい馬鹿をしているという事実は、彼が訂正すべきではないということを意味するものではありません。私の提案は、実際に書かなければならないものを遠隔で近似するものを実装しています。 – Puppy

    +1

    それで、彼が重要なC++の概念を学んでいると仮定するのではなく、これは生産コードであり、直ちに訂正するべきであるという結論にジャンプします。私はこのアプローチに同意しない。 –

    関連する問題