2

可能な限り軽量な非常に大きなサイズ(KBよりもMB以上)のrawバッファーが必要です。データを動的な領域に保持してもらいたいのですが、必ずしも拡張可能である必要はありません。サイズは構築時に設定します。

私は考えましstd::vector<unsigned char>たが:

std::vector<unsigned char>  a(VERY_BIG_SIZE);

データが初期化されています0-これは必要ありません、お金を払いたくないです...これはすでにCPU / RAMの使用率が高い組み込みシステムであり、メモリが割り当てられているが、 usedは仮想的にのみ割り当てられます(つまり、ある程度のアドレススペースが必要ですが、使用されない限り、実際のメモリにマップされません)。

私も考えました:

std::vector<unsigned char> a;
a.reserve(VERY_BIG_SIZE);
std::copy(someData..., a.begin());

意外と期待通りに動作します(どういうわけかこのUBだと思います)-そしてaメモリ全体が初期化されていませんが、すでにお気づきのように、a他のベクトルにコピーすることはできません(a.begin()== a.end())...。


push_back(...)/insert(a.end(), ...)/assign(...)2番目のアプローチでやらなかった理由をどうにかして説明する必要があります。

私はすでに一定のサイズのテンプレートクラスBufferを持っています:

template <size_t SIZE>
class Buffer {
public: 
// this "dirty" solution works, but I would need to add copy stuff by myself...
  Buffer()  { data.reserve(SIZE); }
// this "correct" solution is too heavy:
  Buffer() : data(SIZE) { }

  unsigned char* data() const { return &data[0]; }
private:
  std::vector<unsigned char> data;
  // unsigned char data[SIZE]; // this is not an option because it is not dynamic memory
}; 

私がプライベートに入れることができるものはありますか?Bufferそれはメモリ管理を処理し、コピー可能で初期化されません...そしてメモリは動的に割り当てられます(std :: Vectorのように)。それがunsigned char data[SIZE];オプションではない理由です。

何か案は?

4

4 に答える 4

2

1バイトにパックされ、デフォルトのコンストラクターが初期化されていない(つまり何もしない)コンテンツを残す構造体の標準ベクトルは機能するはずです。

空のベクトルに一括挿入を行うことができ、初期化は受信データからのみであることに注意してください。つまり、vect.insert( vect.end(), random_access_iterator_begin, blah_end )あなたが望むパフォーマンスを持っているかもしれません。

于 2012-11-24T19:31:46.337 に答える
2

はほぼ正しい方向に進んでいvector::reserveます。

vector::assignリザーブをとと組み合わせて使用​​することをお勧めしvector::push_backます。それはまさにあなたが望むことをします。

std::vector<unsigned char> a;
a.reserve(VERY_BIG); // check capacity to see how much memory was reserved
std::copy(someData.begin(), someData.end(), 
          std::back_inserter(a)); // allocation free copy
// or
a.assign(someData.begin(), someData.end());

更新後、独自のバッファを実装します。

template<std::size_t Size>
class buffer {
public:
  buffer() : b_(new unsigned char[Size]) {}
  buffer(const buffer& other) {
    std::copy(other.begin(), other.end(), this->begin());
  }
  buffer& operator=(const buffer& other) { 
    // intentionally no protection against self assignment
    std::copy(other.begin(), other.end(), this->begin());
    return *this;
  }
  ~buffer() { delete [] b_; }
  // move operations, if desired

  unsigned char* begin() { return b_; }
  unsigned char* end() { return b_ + Size; }
  // const versions...

private:
  unsigned char* b_;
};

これには、必要なすべての特性(ヒープ割り当て、ディープコピー可能、作成時に初期化されていない)が必要です。

于 2012-11-24T19:32:37.623 に答える
1

すべての標準コンテナは、要求されたすべてのメモリを初期化します。ただし、予約済みメモリを使用するstd::vector<unsigned char>ことはオプションのようです。次を使用していつでも要素を追加できます。

std::vector<unsigned char> a;
a.reserve(VERY_BIG_SIZE);
a.insert(a.end(), new_data.begin(), new_data.end());

追加の初期化を行わずに、データを適切な場所に直接配置します。もちろん、これは、実際にコンテナーに格納したデータがコンテナーの開始時に連続していることを意味します。大きなバッファ内のランダムな位置にアクセスする必要があり、対応するセクションのみをコピーできるようにしたい場合は、事態はさらに複雑になり、標準C++ライブラリにはこれを簡単に実行できるものはありません。

ところで、ストリームバッファを使用してエリアにデータを書き込むアプローチからこの質問にリンクしたので、アプローチを組み合わせることができますが、ストリームの出力バッファとしてベクターのストレージを使用するよりも複雑になります。 d使用可能なバッファを空にするために必要なベクトルのサイズを追跡し、文字ごとにインクリメントする必要があります。これは技術的には機能しますが、遅くなります。代わりに、ストリームバッファーにバッファーを指定し、ストリームバッファーの終了std::vector<unsigned char>overflow()または終了時に転送しますpubsync()(これがstd::flushトリガーになります)。

于 2012-11-24T19:47:49.480 に答える
0

あなたはいつでもすることができますunsigned char *a = new unsigned char[n];

于 2012-11-24T19:32:55.603 に答える