2017-09-09 28 views
2

ディスクからデータを読み込んで1000個のオブジェクトの配列を埋める必要があります。ただし、すべてのオブジェクトが終了するわけではありません。"空"配列ベクトルメンバーC++

アレイを宣言すると、メモリは1000個のオブジェクト用に予約されます。 私はそれらを1つずつ読むので、メモリを対応する値に設定します。しかし、メンバ#276のオブジェクトが存在しない可能性があり、配列の宣言時にそこにあったものにメモリが設定されたままになります。

配列の特定のメンバーが無効/存在しないという情報を保持するにはどうすればよいですか?

何とかメンバーのすべてのバイトをゼロに設定できましたが、有効なオブジェクトである可能性があります。

明白な解決策は、インデックスのオブジェクトが存在するかどうかに応じて1または0に設定される別のバイト配列を追加することですが、あまりエレガントではありません。

代わりにベクターでこれを行うことができますか?それは何とか空の値を格納することができますか?

+0

'std :: pair 'を使うと、 'bool'部分はオブジェクトが読み込まれたかどうかを示しますか? – Fureeish

+0

オブジェクトインスタンスの代わりにポインタを使用しますか? –

+0

構造体やクラスのようにオブジェクトの配列であれば、デフォルトの構築済みオブジェクトを明確にセンチネル/空のオブジェクトにします。空白の理由がインデックス値を保持している場合は、オブジェクトの一部を作成するか、mapまたはunordered_mapのようなキー/値コンテナを使用して順序どおりに処理する必要があるかどうかを検討してください。 –

答えて

1

代わりにベクターでこれを行うことができますか?

なし

この情報(存在するかどうか)を保存するために余分なスペースを使用するか、存在しないオブジェクトのセンチネル値を使用する場合はもちろんです。 std::vectorには、格納する要素の数に応じてサイズを変更する強力な機能があります。あなたの要求を満たすことができれば、それはその能力を失うでしょう。

std::unordered_mapを使用します。すべてのキーはオブジェクトのインデックス(例:#276)になり、値は実際のオブジェクトになります。オブジェクトが存在しない場合は、そのキーをマップに挿入しないでください。

またはデータを効率的に反復処理する必要がある場合は、std::mapです。 Choosing between std::map and std::unordered_map


あなたの配列のセルを空にするセンチネル値を見つけるのは本当に難しいと思います。例えば、あなたが既にあなたのケースではないと思うメモリのどこかに既にデータがあるならば、オブジェクト全体を格納する配列の代わりにポインタの配列を使うことができます。 NULLポインタが空であるセルに使用されるであろうことは明らかであろう


別のオプションは、このように、ペアのアレイを使用することであろう。第2オペランドは、対応するセルであるかどうかを示すstd::pair<myClass, bool>、空かどうか。

さらに、代わりにstd::vector<bool>を使用することができます。Why does std::vector<bool> has no .data()?で説明されているように、非常にメモリ効率が良い(余分なデータ構造のアプローチに従うことに決めた場合)。ただし、索引のパフォーマンスが不足します。

+1

私は順序付けされていないマップアプローチが好きです。コードをできるだけシンプルにすることです。 – Karlovsky120

+0

はい@ Karlovsky120あなたのデータのセンチネル値を考えることができない場合、このソリューションはクリーンなコードを生成すると思います! ;)いい質問BTW、私はupvoted! – gsamaras

+0

私はおそらくそれらを繰り返していなければならないので、私は通常の地図と一緒に行くかもしれません... – Karlovsky120

1

論理的に言えば、存在する値と実際にデータが格納されている値の両方を追跡する必要があります。これを行うための最善の方法はありません。あなたがしていることによってあなたの選択は変わります。

場合によっては実装がそのようなものではないようですが、特別な値、nullptrまたは-1をセンチネルとして予約して空のスロットをマークすることができます。あなたは既にこのオプションがここには存在しないと述べました。だから、私たちはそれを支配します。

もう1つの非常に妥当なオプションは、スロットが使用されているかどうかを示すスロットマーキングごとにパラレルビットベクトルまたは補助データのいずれかを格納することです。ビットベクトルを使用する場合、ここで必要となる余分なメモリは、要素自体に使用するメモリに比べて非常に小さいです。

上記の2つのアプローチの欠点は、本当に巨大な配列、たとえば何百万もの要素がある場合、スロット自体と余分な簿記の両方で未使用スロットに1トンのメモリを使用することです。別の選択肢は、std::mapまたはstd::unordered_mapのような疎なデータ構造を使用して、インデックスから要素へのキーであり、実際に使用される疎構造に要素をロードするだけです。個々の要素を検索する場合のパフォーマンスコストはこのように少し遅くなりますが、メモリの利便性は重要な意味を持ちます。

+0

正しいとマークする答えはあなた、あなた、またはgsamarasはわかりません。 – Karlovsky120

1

まず、実際には最適化を気にするだけの十分なメモリを心配していることを確認してください。彼らが巨大で、あなたがそれらがまばらになることを期待しない限り、1000オブジェクトはそれほど多くはありません。インデックスは重要ですか?つまり、2つのオブジェクトをロードすると、配列の要素0,1に置くことができますか、配列内のその位置が重要で、各オブジェクトには使用する特定の配列インデックスがありますか?その場合、配列に大きな穴ができてしまい、どの要素が使用されているかどうかの指標が必要になることがあります(これはお勧めしません)。代わりに、 nullの場合、使用される要素が割り当てられ、対応するポインタが適切なインデックスでそれらに設定されます。配列をコンパクトにすることができれば、ベクターを使うこともできます。

もう1つの方法は、項目を配列に入れないことですが、挿入する要素だけを保持するツリーマップのようなものですが、配列インデックスに似たキーを使用して見つけることができます。

(注:std :: unordered_mapはstd :: mapより高速ですが、ハッシュテーブルはメモリを過剰に割り当てます(割り当てられた領域の70%が使用されていると頻繁に負荷がかかると見なされます)