当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++进阶与实例

用C++实现对内存的管理(2)

 原地重新分配(Inplace Resizing)

  许多的C++程序员都梦寐以求有一种标准的原语(也即操作符),用于原地重新分配内存。众所周知,C语言中有realloc,其尽可能的原地重新分配内存,并在涉及到复制数据时使用memcpy,但memcpy并不适合于C++对象,所以,realloc也不适用于C++的对象。因此,任何一种renew原语都不能用标准C分配符来实现,这就是为什么C++中没有renew的原因。

  以下演示了一种改进后的方法,可应用于C++代码中的原地重新分配,请看:

const int n = 10000;
Vec v;
for (int i = 0; i < n; ++i)
v.push_back(0);

  Metrowerks的Howard Hinnant一直在为实现应用于CodeWarrior标准库的原地扩展而努力,用他自己的话来说:

  现在有一个可进行原地重新分配的vector<T, malloc_allocator<T>>,当Vec为一个不带原地扩展的vector<int>时,耗时为0.00095674秒;当Vec为一个带有原地扩展的vector<int>时,耗时为0.000416943。由此可看出,内存的原地重新分配,所带来的性能提升,非常之明显。

  既然有了原地重新分配所带来的好处,而堆中的每个层都能控制其自己的分配算法和数据结构,请看下面的堆层接口:

template <class T>
struct Allocator : public T {
 void * malloc(size_t sz);
 void free(void* p);
 size_t expand(void* p, size_t min, size_t max);
};

  扩展在语义上的意思是,尝试通过p扩展指向在两者之间最大尺寸的块,并返回期望扩展的任意大小内存块。幸运的是,一个层不必关心用于扩展的子程序,如果所有顶层的分配方法都继承自以下的类,那么一切都将工作正常:

struct TopHeap {
 size_t expand(void*, size_t, size_t) {
  return 0;
 }

 protected:
  ~TopHeap() {}
};

  结论

  可配置的内存分配算符,是一种实用的、一体化的解决方案,可取代专门或通用的内存分配操作符。此外,HeapLayers的分层架构支持更简单的调试,并且具有非并行的可扩展性。表1演示了一个在HeapLayers中,层实现的相关子集,其中有许多值得讨论的地方,如多线程操作中的闭锁堆、STL适配程序、各种不同的工具堆、还有怎样结合多个层来创建一个通用的内存分配算符,另外,千万记住不要忘了在析构函数中释放内存,祝大家编程愉快!

  表1:部分HeapLayers库

顶层堆
mallocHeap 取代malloc的层
mmapHeap 取代虚拟内存管理的层
sbrkHeap 取代sbrk(连续内存)构建块堆的层
AdaptHeap 使数据结构可作为堆使用
BoundedFreelistHeap 有长度限制的释放列表
ChunkHeap 以给定大小的块来管理内存
CoalesceHeap 执行拼接与拆分
FreelistHeap 一个释放列表(用于捕捉释放的对象)
组合堆
HybridHeap 对小对象使用一个堆,而对大对象使用另一个堆
SegHeap 用于分配方法的一般分割
StrictSegHeap 用于分配方法的严格分割
工具层
ANSIWrapper 提供与ANSI-malloc的兼容性
DebugHeap 检查多种分配错误
LockedHeap 为保证线程安全的闭锁堆
PerClassHeap 使用一个堆作为每个类的分配算符
PHOThreadHeap 带有自有分配算符私有堆
ProfileHeap 收集并输出碎片统计
ThreadHeap 一个纯私有堆分配算符
ExceptionHeap 当父类堆超出内存时,抛出一个异常
TraceHeap 输出有关内存分配的跟踪信息
UniqueHeap 引用一个堆对象的堆类型
对象表示
CoalesceableHeap 为拼接提供支持
SizeHeap 在头部中记录对象大小
特殊用途的堆
ObstackHeap 专门优化用于类似堆栈行为或快速大小调整的堆
ZoneHeap 一个区域分配算符
XallocHeap 优化用于类似堆栈行为的堆
通用堆
KingsleyHeap 快速但多碎片的堆
LeaHeap 速度不快,但碎片很少的堆
相关内容
赞助商链接