在Vector Container中使用placement new

时间:2011-04-22 02:54:15

标签: c++ vector placement-new

如果我有一个容器:

std::vector<T*> elements;

我可以使用placement new来分配我的对象,以便所有对象都是连续分配的吗?所以我可以这样做:

size_t elementIndex = someRandomElement - elements[0];

其中someRandomeElement是来自elements的随机元素,elementIndex将存储someRandomElement的正确索引,以便elements[elementIndex] == someRandomElement

这是我当前实现的内存管理器所必需的。我有一个我今天能够完成的实现,但它需要元素(可以是体素,三角形或其他任何东西)来使用GetIndex()和SetIndex()函数,以便当元素作为指针返回时,我可以找出elements数组中元素的索引,这意味着我无法改变的任何元素(比如说Ogre :: Vector3)都不能使用管理器(在我的情况下,我需要它们使用它们)因为它们正在分裂内存)。

我唯一的另一个解决方案是拥有一个充当访问器的结构,并且具有索引以及指向元素的指针,尽管这会导致内存使用量增加(考虑到我现在正在使用500万个元素)

  

注意:我今天发布了一个similar question,但是那里的答案做出了一些完全违背我要求的假设。其中一个要求是向量必须填充指向T的指针,否则需要更改大部分代码库。其次,初始化超过100,000(大约)元素会导致bad_alloc异常。每个元素的大小为196个字节(我已设法将其减少到132个字节)。

2 个答案:

答案 0 :(得分:2)

要使指向的对象连续,您有两个合理的选择:

  • 使用new[]创建一个足以容纳所有元素的元素数组,然后为其分配新值并将其地址放入元素中
  • 使用malloc()创建一个足够大的未初始化的内存区域来保存它们(它可能会严格对齐,但你应该知道这个问题),然后使用展示位置new构建你的那个记忆中的元素

不要使用new[]然后使用new,因为默认构造的元素在放置之前不会被破坏,因为它会占用内存...因此构造函数采用的任何资源,计数器维护等等。析构函数无法正确释放/更新。

如果你没有足够的内存来分配大数组,那么很明显你不能这样做......就这么简单。预计100,000个单独的new T需要比单个new T[100000]更多的内存,但是......存在与分配相关的填充和堆管理开销。

答案 1 :(得分:1)

std::bad_alloc异常可能是因为您试图分配过大的连续内存块。因此,请考虑使用std::deque<T>

如果您因某种原因决定仍然需要std::vector<T*>,则可以存储指向std::deque<T>中元素的指针。只要您只添加和删除序列开头或结尾的元素,您就不必担心指针被无效。