質問

これはしばらくの間私に悩まされてきた質問です。私はいつも、C ++は「削除」するように設計されるべきだと考えていました。演算子(括弧なし)は" new []"でも機能します。演算子。

私の意見では、これを書いています:

int* p = new int;

1つの要素の配列を割り当てるのと同じです:

int* p = new int[1];

これが当てはまる場合、「削除」演算子は常に配列を削除する可能性があり、" delete []"は必要ありません。演算子。

" delete []"が表示される理由はありますか演算子はC ++で導入されましたか?私が考えることができる唯一の理由は、配列を割り当てるとメモリフットプリントが小さく(配列サイズをどこかに保存する必要があるため)、「削除」を区別することですvs" delete []"小さなメモリの最適化でした。

役に立ちましたか?

解決

それは、個々の要素のデストラクタが呼び出されるようにするためです。はい、PODの配列の場合、大きな違いはありませんが、C ++では、重要なデストラクタを持つオブジェクトの配列を使用できます。

今、あなたの質問は、 new delete new [] delete [] new [] delete [] を削除しますか? Stroustrupの「デザインと進化」に戻ります。 C ++の機能を使用しない場合は、少なくとも実行時にそれらの機能を購入する必要はない、と彼が言った本。現状では、 new または delete は、 malloc および free と同じくらい効率的に動作します。 delete delete [] の意味がある場合、実行時に余分なオーバーヘッドが発生します(James Curranが指摘したように)。

他のヒント

気をつけて、私は質問のすべてのポイントを逃しましたが、私は元の答えを補足として残します。 delete []がある理由は、かなり前にdelete [cnt]があったためです。今日でもdelete [9]またはdelete [cnt]を記述しても、コンパイラは[]の間を無視しますが、[ok]をコンパイルします。当時、C ++は最初にフロントエンドで処理され、次に通常のCコンパイラに送られました。彼らは、カーテンの下のどこかにカウントを保存するトリックを行うことができませんでした。下位互換性のために、コンパイラはおそらく配列のカウントとして[]の間に指定された値を使用します。そのような値がない場合、プレフィックスからカウントを取得するため、両方の方法で機能します。その後、[]の間に何も入力せず、すべてが機能しました。今日、" delete []"とは思いません。必要ですが、実装はそれをそのように要求します。

元の答え(ポイントを逃します)::

"削除"単一のオブジェクトを削除します。 " delete []"オブジェクト配列を削除します。 delete []が機能するために、実装は配列内の要素の数を保持します。 ASMコードをデバッグして、これを再確認しました。テストした実装(VS2005)では、カウントはオブジェクト配列のプレフィックスとして保存されました。

" delete []"を使用する場合単一のオブジェクトでは、カウント変数がゴミであるため、コードがクラッシュします。 「削除」を使用する場合オブジェクト配列の場合、矛盾があるため、コードがクラッシュします。今、これらのケースをテストしました!

" deleteは、配列に割り当てられたメモリを削除するだけです。"別の答えの文は正しくありません。オブジェクトがクラスの場合、deleteはDTORを呼び出します。 DTORコードにブレークポイントを配置してオブジェクトを削除するだけで、ブレークポイントがヒットします。

私に起こったことは、コンパイラ&ライブラリでは、「new」によって割り当てられたすべてのオブジェクトがオブジェクト配列である場合、「delete」を呼び出しても問題ありません。単一オブジェクトまたはオブジェクト配列用。単一のオブジェクトは、カウントが1のオブジェクト配列の特殊なケースにすぎません。とにかく、私が見逃しているものがあるかもしれません...

他の誰もがあなたの質問のポイントを見逃しているように見えるので、私は数年前に同じ考えを持っていて、答えを得ることができなかったことを付け加えます。

私が考えることができる唯一のことは、単一のオブジェクトを配列として扱うための非常に小さな余分なオーバーヘッドがあることです(不要な" for(int i = 0; i< 1; ++ i )")

これに対処する他の回答がないため、これを追加します:

Array delete [] は、ベースへのポインタークラスでは使用できません-コンパイラは、 new [] を呼び出したときにオブジェクトの数を保存しますが、オブジェクトのタイプやサイズは保存しません(Davidが指摘したように、C ++では、使用していない機能に対してほとんど支払いをしません)。ただし、スカラー delete は基本クラスを通じて安全に削除できるため、通常のオブジェクトクリーンアップとポリモーフィッククリーンアップの両方に使用されます。

struct Base { virtual ~Base(); };
struct Derived : Base { };
int main(){
    Base* b = new Derived;
    delete b; // this is good

    Base* b = new Derived[2];
    delete[] b; // bad! undefined behavior
}

ただし、反対の場合-非仮想デストラクタ-スカラー delete は可能な限り安くする必要があります-オブジェクトの数やオブジェクトのタイプをチェックするべきではありません削除されました。コンパイラーは :: operator delete を呼び出すだけでよいため、組み込み型またはplain-old-data型の削除は非常に安価になります:

int main(){
    int * p = new int;
    delete p; // cheap operation, no dynamic dispatch, no conditional branching
}

メモリ割り当ての網羅的な処理ではありませんが、これがC ++で利用可能なメモリ管理オプションの幅を明確にするのに役立つことを願っています。

マーシャルクラインには、このトピックに関する情報

delete [] は、各メンバーのデストラクタが呼び出されるようにします(型に該当する場合)。 delete は配列に割り当てられたメモリを削除するだけです。

こちらをご覧ください: http://www.informit。 com / guides / content.aspx?g = cplusplus& seqNum = 287

いいえ、配列サイズはC ++のどこにも保存されません。(このステートメントが不正確であることを指摘してくれたすべての人に感謝します。)

私はアーロンの答えに少し混乱しており、delete []が必要な理由と場所が完全にはわからないことを率直に認めています。

彼のサンプルコードを使用していくつかの実験を行いました(いくつかのタイプミスを修正した後)。ここに私の結果があります。     タイプミス:〜Baseには関数本体が必要     ベース* bが2回宣言されました

struct Base { virtual ~Base(){ }>; };
struct Derived : Base { };
int main(){
Base* b = new Derived;
delete b; // this is good

<strike>Base</strike> b = new Derived[2];
delete[] b; // bad! undefined behavior
}

コンパイルと実行

david@Godel:g++ -o atest atest.cpp 
david@Godel: ./atest 
david@Godel: # No error message

delete []が削除された修正プログラム

struct Base { virtual ~Base(){}; };
struct Derived : Base { };

int main(){
    Base* b = new Derived;
    delete b; // this is good

    b = new Derived[2];
    delete b; // bad! undefined behavior
}

コンパイルと実行

david@Godel:g++ -o atest atest.cpp 
david@Godel: ./atest 
atest(30746) malloc: *** error for object 0x1099008c8: pointer being freed was n
ot allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

もちろん、最初の例でdelete [] bが実際に機能しているかどうかはわかりません。コンパイラーのエラーメッセージが表示されないことしかわかりません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top