19

を使用して配列を割り当てる場合new []、ポインタからその配列のサイズがわからないのはなぜですか? 実行時に知る必要があります。そうdelete []しないと、解放するメモリの量がわかりません。

私が何かを見逃していない限り?

4

4 に答える 4

15

典型的な実装では、動的メモリブロックのサイズはブロック自体に何らかの形で格納されます-これは真実です。しかし、この情報にアクセスするための標準的な方法はありません。(実装は、それにアクセスするための実装固有の方法を提供する場合があります)。これは、との関係です。malloc/freeこれは、との関係new[]/delete[]です。

実際、一般的な実装では、呼び出しの生のメモリ割り当てnew[]/delete[]は、最終的には実装固有のmalloc/freeようなペアによって処理されdelete[]ます。つまり、割り当てを解除するメモリの量を気にする必要はありません。つまり、内部free(またはそれが何であれ)を呼び出すだけです。名前が付けられています)、それはそれを処理します。

delete[]ただし、知っておく必要があるのは、配列要素タイプに重要なデストラクタがある状況で破棄する要素の数ですそして、これがあなたの質問です-ブロックのサイズではなく、配列要素の数です(これらの2つは同じではなく、ブロックは配列自体に実際に必要なものよりも大きくなる可能性があります)。このため、配列内の要素の数は通常、ブロック内にも格納され、後で適切な配列要素の破棄を実行するためnew[]に取得されます。delete[]この番号にアクセスするための標準的な方法もありません。

(これは、一般的な場合、によって割り当てられる一般的なメモリブロックは、物理ブロックサイズ(バイト単位)と配列要素数の両方new[]を独立して同時に格納することを意味します。これらの値は、さまざまなレベルのC++メモリ割り当てメカニズム(rawメモリアロケータとそれ自体)によって格納されます。それぞれ-そして、いかなる方法でも互いに相互作用しないでください)。new[]

ただし、上記の理由により、配列要素の数は通常、配列要素の型に重要なデストラクタがある場合にのみ保存されることに注意してください。つまり、このカウントは常に存在するとは限りません。これが、そのデータにアクセスするための標準的な方法を提供できない理由の1つです。データを常に保存するか(メモリを浪費する)、デストラクタの種類によって可用性を制限する必要があります(混乱を招きます)。

int上記を説明するために、 sの配列を作成する場合

int *array = new int[100];

配列のサイズ(つまり100)は、それを気にしない(デストラクタがない)ため、通常はによって格納されnew[]ません。ブロックの物理サイズ(バイト単位など)(400バイト以上など)は、通常、rawメモリアロケータによってブロックに格納されます(およびによって呼び出されるrawメモリデロケータによって使用されます)が、一部の実装では420になる可能性があります。 -特定の理由。したがって、このサイズから正確な元の配列サイズを導出することはできないため、このサイズは基本的に役に立ちません。delete[]intdelete[]

于 2010-03-09T00:20:40.720 に答える
7

ほとんどの場合、アクセスできますが、アロケーターに関する詳細な知識が必要であり、移植できません。C++ 標準では、実装がこのデータを格納する方法を指定していないため、データを取得するための一貫した方法はありません。異なるアロケーターが効率のために異なる方法でそれを保存したいと思うかもしれないので、私はそれが指定されていないと信じています。

于 2010-03-09T00:09:29.867 に答える
5

たとえば、割り当てられたブロックのサイズが必ずしも配列と同じサイズであるとは限らないため、これは理にかなっています。要素の数を格納する (各要素のデストラクタを呼び出す)ことは事実ですnew[]が、空のデストラクタには必要ないため、その必要はありません。各方法には長所と短所があるため、配列の長さを格納する場所を実装する標準的な方法 ( C++ FAQ Lite 1C++ FAQ Lite 2 ) もありません。new[]

つまり、実装について何も指定しないことで、割り当てを可能な限り高速かつ安価に行うことができます。(実装で、配列のサイズと割り当てられたブロックのサイズを毎回格納する必要がある場合は、不要なメモリが浪費される可能性があります)。

于 2010-03-09T00:10:39.170 に答える
3

簡単に言えば、C++ 標準ではこれをサポートする必要はありません。コンパイラの内部について十分に知っていれば、この情報にアクセスする方法を理解できる可能性がありますが、それは一般的に悪い習慣と見なされます。ヒープ割り当て配列とスタック割り当て配列では、メモリ レイアウトが異なる場合があることに注意してください。

基本的に、ここで話しているのは C スタイルの配列でもあることを覚えておいてください -newdeleteは C++ 演算子ですが - 動作は C から継承されています。 STL (例: std::vector、std::deque)。

于 2010-03-09T00:18:11.897 に答える