あまり重要ではないと思いますが、プログラムは delete[] のために長さを保存する必要があるため、この「保存された情報」を取得できないのはなぜですか?
9 に答える
実装は長さを格納する必要があるだけで、通常は、型が自明に破壊できず (つまり、デストラクタへの呼び出しを生成する必要がある)、配列が new[] 演算子で作成された場合にのみ格納します。
配列型のそのプロパティは配列のサイズとは関係がないため、単純に長さを「クッキー」と呼ぶ方がよりエレガントです。
完全な配列オブジェクト (単なるポインターではない) の長さを取得するには、std::extent< decltype( arr ) >::value
またはを使用できますstd::end( arr ) - std::begin( arr )
。
new[]
デストラクタを持つクラスで使用するのはコードの匂いです。std::vector
代わりに検討してください。オーバーヘッドと raw new[]
(割り当てられる必要があるすべてのバイトを考慮して、それらがどこにあっても) は 1 ポインター分のバイトであり、その利点は計り知れません。
ケースを考えてみましょう:
char* a = new char[100];
a
少なくとも 100 文字のバッファを指す必要がありますが、これを満たすためにシステムがより大きなバッファを割り当てた可能性があります。
これを念頭に置いて、後で適切にバッファの割り当てを解除できる限り、システムはプログラムが要求したサイズをすぐに忘れてもかまわないことがわかります。(割り当てられたバッファのサイズを記憶するか、開始へのポインタのみが必要なスマートデータ構造でメモリ割り当てを行うことにより)
したがって、一般的なケースでは、探している情報は実際にはどこにも保存されていません。
私の理解では、C++ の哲学は、やむを得ない場合を除き、コストがかかる可能性のある機能を人々に強制しないことです。
この情報を保存するには追加のコストがかかる可能性があり、ユーザーは情報が必要ない場合にそのコストを支払いたくない場合があります。また、必要に応じて自分で長さを保存するのは簡単なので、配列を使用するすべての人にコストがかかる言語機能を提供する理由はありません。
すべての配列が によって割り当てられるわけではありませんnew
。
void f(int* arr, size_t n)
{
length(arr); // ???
}
int main()
{
int a[5];
f(a);
}
(std::end(arr) - std::begin(arr))
ただし、配列の先頭を指すポインターではなく、配列に対してのみ機能しますが、書くのは簡単です。
適切な配列、つまり については、すでにint a[length]
その機能を持っています。
#define length(A) (sizeof(A) / sizeof(*A))
これで完了です。
ポインターが指す配列の長さを取得することについて話している場合、ポインターと配列は2つの異なる概念であり、必要に応じて適切な配列がポインターに「減衰」し、ポインターを介して配列にアクセスしたとしても、それらを結合することは意味がありません算術。
しかし、それを考慮せずに技術的な側面について話したとしても、配列の長さを特定の方法で格納する に依存する可能性があるため、C++
ランタイムは配列の長さを認識できない可能性があります。only by :空でないデストラクタがある場合にのみ、ランタイムは追加情報のみを保存します。かなり雑な写真ですよね?new
malloc
free
C++
この情報を格納する実装次第だからです。そのため、長さ(配列)を行う一般的な方法はありません
しかし、配列の長さは正確には何ですか? 配列のバイト数ですか、それとも配列の要素数ですか?
例: 100 バイト サイズのクラス A の場合、
A* myArray = 新しい A[100];
length(myArray) は 100 または 100 * 100 を返す必要がありますか? 誰かが 100 を望むかもしれませんし、誰かが 10000 を望むかもしれません。したがって、どちらにも本当の議論はありません。
長さは、すべての実装に格納されているわけではありません。たとえば、C++ ではガベージ コレクション (boehmgc など) が可能であり、多くのコレクターは長さを知る必要はありません。従来のアロケータでは、格納される長さが実際の長さ、つまり使用される長さではなく、割り当てられる長さよりも大きくなることがよくあります。
サポートする言語の「配列」のように最も機能する C++ 型length(array)
はstd::vector<>
であり、std::vector<>::size()
.
もちろん、プレーン[]
配列のサイズは、サイズが明示されているスコープでコンパイラーに認識されていますが、サイズがコンパイラーに認識されていないスコープにそれらを渡すことは可能です。これにより、疑問文をサポートする必要がある言語よりも配列のようなデータを処理する方法が C++に多くなりlength
ます(サイズが常に渡されることを保証する必要があるため)。