2

我需要尽可能轻的非常大的原始缓冲区(比方说 MB 多于 KB)。我想让它把数据保存在动态区域中,不一定是可增长的,我会在构建时设置大小。

我想过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(...)采用第二种方法。

我已经有固定大小的模板类缓冲区:

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

我建议将 reserve 与vector::assignand结合使用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>带有保留内存的 a 似乎是一种选择:您始终可以使用添加元素

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>onoverflow()或 when pubsync()ing 流缓冲区的末尾(这是std::flush触发的原因)。

于 2012-11-24T19:47:49.480 回答
0

你总是可以做到unsigned char *a = new unsigned char[n];的。

于 2012-11-24T19:32:55.603 回答