web-dev-qa-db-ja.com

動的に割り当てられた配列のサイズを見つける

この方法で割り当てられたバッファの長さを取得できないのはなぜですか。

AType * pArr = new AType[nVariable];

同じアレイの割り当てが解除された場合

delete [] pArr;

ランタイムは、割り当てを解除する量を知っている必要があります。配列を削除する前に長さにアクセスする方法はありますか?いいえの場合、長さをフェッチするようなAPIが提供されていないのはなぜですか?

25
Ram

配列を削除する前に長さにアクセスする方法はありますか?

いいえ、それを判断する方法はありません。
標準では、実装がnewを介して要求された要素の数の詳細を記憶して提供する必要はありません。
実装では、要素の数を記憶する代わりに、割り当てられたメモリブロックの最後に特定のビットパターンを挿入するだけで、メモリを解放しながらパターンを検索するだけで済みます。
要するに、それは単に実装の詳細です。


ちなみに、この問題を実際に克服するには2つのオプションがあります。

  1. size()またはのようなメンバー関数を提供するstd::vectorを簡単に使用できます。
  2. あなたは単に自分で簿記をすることができます。

newatleast要求しただけの十分なメモリを割り当てます。
長さを簡単に計算できるように、要求したメモリの量はすでにわかっています。 sizeofを使用して、各アイテムのサイズを確認できます。

Total memory requested / Memory required for 1 item = No of Items
7
Alok Save

ランタイムは、割り当てられた量を認識します。ただし、このような詳細はコンパイラ固有であるため、クロスプラットフォームで処理する方法はありません。

同じ機能が必要でサイズを追跡できる場合は、次のようにstd :: vectorを使用できます。

std::vector< AType > pArr( nVariable );

これには、RAIIを使用するという追加の利点もあります。

6
Goz

deleteオペレーターは、freeシステムコールが知らないように、割り当てられたメモリを解放するためにサイズを知る必要はありません。これは、その問題がコンパイラのランタイムシステムではなく、オペレーティングシステムに委ねられているためです。

ランタイムは、割り当てられたのと同じ量の割り当てを解除する必要があり、何らかの方法で(通常は非常に間接的に)これを追跡します。ただし、割り当てられた量から要素の数を取得する信頼できる方法はありません。割り当てられた量は、要素の数に各要素のサイズを掛けた値より少なくすることはできませんが、多くの場合、それより多くなります。たとえば、配置に関する考慮事項は、new char[5]およびnew char[8]は多くの場合、同じ量のメモリを割り当てます。また、厳密に必要なメモリよりもはるかに多くのメモリを割り当てることができるさまざまな割り当て戦略があります。

3
James Kanze

いいえ、そうではありません。少なくとも、プラットフォームに依存しない、定義された方法ではありません。

ただし、ほとんどの実装では、動的に割り当てられた配列のサイズが実際の配列の前に格納されます。

2
Luchian Grigore

C++には、生のポインターから動的に割り当てられた配列のサイズを取得する移植可能な方法はありません。

MSVCおよびWIN32では、_msize(void *)関数を使用して、割り当てられたブロックのサイズを取得できます。

詳細については、 https://msdn.Microsoft.com/en-us/library/z2s077bc.aspx を参照してください。

1
vre

なぜこのような追加情報を少ししないのですか?

template <typename T> class AType
{
public:

    AType(size_t s) : data(0)
    {
        a_size = s;
        data = new T[s];
    }
    ~AType() {
        if (data != nullptr)
            delete [] data;
    }

    size_t getSize() const
    {
        return a_size * sizeof(T);
    }

private:
    size_t a_size;
    T* data;
};
0
Ilian Zapryanov