在c ++中使用realloc

def*_*ode 15 c c++ memory-management realloc

std::realloc如果malloc内存包含非pod类型,则在c ++中是危险的.似乎唯一的问题是,std::realloc如果不能在原位增长记忆,就不会调用类型析构函数.

一个微不足道的工作将是一个try_realloc功能.如果它不能在原地生长,而不是malloc'ing新的记忆,它将简单地返回false.在这种情况下,可以分配新内存,将对象复制(或移动)到新内存,最后释放旧内存.

这看起来非常有用. std::vector可以充分利用这一点,可能避免所有副本/重新分配.
抢先阻燃:从技术上讲,这与Big-O性能相同,但如果矢量增长是您应用中的瓶颈,即使Big-O保持不变,x2加速也很好.

但是,我找不到任何有效的c api try_realloc.

我错过了什么吗?是try_realloc不是像我想象的那么有用吗?是否存在一些try_realloc无法使用的隐藏错误?

更好的是,是否有一些记录较少的API表现得如此try_realloc

注意:我很明显,在这里的库/平台特定代码中.我并不担心try_realloc本来就是一种优化.


更新: 继Steve Jessops评论是否vector使用realloc更有效率后,我写了一个概念验证来测试.该realloc-vector模拟载体的增长模式,但有realloc的替代选项.我在程序中运行了一百万个元素.

为了比较,vector必须分配19次,同时增加到一百万个元素.

结果,如果realloc-vector是唯一使用堆的结果是令人敬畏的,3-4分配同时增长到百万字节的大小.

如果将realloc-vector其与vector66%的速度一起使用,realloc-vector 那么结果的速度就不那么大了,在增长期间分配8-10次.

最后,如果realloc-vector与以vector相同速率增长的a一起使用,则realloc-vector分配17-18次.在标准向量行为上仅保留一个分配.

我不怀疑黑客可以通过游戏分配大小来提高节省,但我同意Steve的观点,即编写和维护这样一个分配器所付出的巨大努力并不适用.

Ste*_*sop 11

vector通常以大增量增长.除非你仔细安排事情,以便在向量的内部缓冲区之上存在大量的空闲地址(实际上需要分配整个页面,因为很明显你不能进行其他分配,否则你不能在没有重新定位的情况下重复这样做.稍后在同一页面上).

所以我认为,为了在这里获得一个非常好的优化,你需要的不仅仅是一个"琐碎的解决方法",如果可能的话,可以进行廉价的重新分配 - 你必须做一些准备才能使它成为可能,并且准备成本会让你解决空间问题.如果你只针对某些向量,那些表明它们会变大的向量,那么它就毫无意义,因为它们可以表明reserve()它们会变大.如果你有一个巨大的地址空间,你只能为所有向量自动执行它,这样你就可以在每个向量上"浪费"它的一大块.

据我了解,Allocator概念没有重新分配功能的原因是为了保持简单.如果std::allocator有一个try_realloc函数,那么每个Allocator都必须有一个(在大多数情况下无法实现,并且只需要总是返回false),否则每个标准容器都必须专门用于std::allocator利用它.这两个选项都不是一个很好的Allocator接口,虽然我认为对于几乎所有Allocator类的实现者来说,添加一个do-nothing try_realloc函数并不是一项巨大的努力.

如果vector由于重新分配而缓慢,deque可能是一个很好的替代品.

  • @caspin:我认为你的方式会增加,纯粹靠运气,在向量想要扩展到缓冲区时,缓冲区之上有很大程度的可用内存.这很好,但正如我所说的那样,我认为值得构建到界面中是非常罕见的,因为"deque"存在以支持增长无法预测且复制性能糟糕的情况.也许该标准的作者也同样认为,或者他们可能有其他原因 - 我不知道. (3认同)