在矢量容器中使用新放置

Using placement new in a Vector Container

本文关键字:新放      更新时间:2023-10-16

如果我有一个容器:

std::vector<T*> elements;

我是否可以使用放置新来分配我的对象,以便所有对象都连续分配?这样我就可以做这样的事情:

size_t elementIndex = someRandomElement - elements[0];

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

这是我当前实现内存管理器所必需的。我有一个我今天能够完成的实现,但它需要元素(可以是体素、三角形或其他任何东西(具有 GetIndex(( 和 SetIndex(( 函数,以便当元素作为指针返回时,我可以在 elements 数组中找到元素的索引, 这意味着任何我无法更改的元素(假设 Ogre::Vector3(都无法使用管理器(就我而言,我需要它们使用它,因为它们正在对内存进行碎片(。

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

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

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

  • 使用 new[] 创建一个足够大的元素数组来容纳所有元素,然后将新值分配给它们并将它们的地址放入元素中
  • 使用
  • malloc(( 创建一个足够大的未初始化内存区域来容纳它们(它可能足够严格对齐,但您应该意识到这个问题(,然后使用放置new在该内存中构造您的元素

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

如果您没有足够的内存来分配大数组,那么显然您无法做到这一点......就这么简单。 不过,预计 100,000 个单独的new T需要比单个new T[100000]更多的内存......存在与分配关联的填充和堆管理开销。

std::bad_alloc异常

可能是因为您尝试分配的连续内存块太大。 因此,请考虑改用std::deque<T>

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