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
其与vector
66%的速度一起使用,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
可能是一个很好的替代品.