2.3 动态空间管理

Posted nk-007

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2.3 动态空间管理相关的知识,希望对你有一定的参考价值。

空间管理方法主要分为两类:静态的和动态的。顾名思义,静态空间管理即是在向量生命期内,其内部数组所占物理空间的容量不允许增加,这种策略既拘泥固化且空间管理效率底下,因此常采取动态空间管理策略,具体方法是使向量可扩充。
 
可扩充向量既能够在空间不足达到上溢临界点时扩充向量空间,同时能够在空间需求不甚强烈,达到下溢临界点时缩容空间向量。
 
扩容
 
对向量实现扩容的难点在于如何实现扩容?新的容量取作多少才算适宜?
 
如何扩容?——先保留,再扩容,后迁移。
 
因为向量是寻秩访问,上下秩之间物理地址连续,所以在扩容的过程中必须保证物理空间必须地址连续,所以可行的方法是:通过申请更大容量的内部数组,将原先内部数组中的成员集体搬迁到新的空间,此后方可顺利地插入新元素e而不致数据溢出。原数组所占空间及时释放,并归还操作系统。实现代码如下:
 
                            template <typename T> void Vector<T>::expand() {
       if (_size < _capacity)
               return;
       if (_capacity < DEFAYLT_CAPACITY)
               _capacity = DEFAYLT_CAPACITY;//使其不小于默认容量即最小容量
       T* oldElem = _elem;
       _elem = new T[_capacity <<= 1];//容量加倍
       for (int i = 0; i < _size; i++)
               _elem[i] = oldElem[i];//复制原向量内容
       delete[] oldElem;
 
}
 
有趣的是,最调用insert()接口插入新元素之前,都要先调用该算法用于检查数组容量。
 
缩容
 
当向量的规模远远小于内部数组的容量,称为下溢时,我们会采取缩容操作。具体算法如下:
 
template <typename T> void Vector<T>::shrink() {
       if (_capacity < DEFAYLT_CAPACITY << )
               return;
       if (_size << 2 > _capacity)
               return;
       T* oldElem = _elem;
       _elem = new T[_capacity >>= 1];//容量加倍
       for (int i = 0; i < _size; i++)
               _elem[i] = oldElem[i];//复制原向量内容
       delete[] oldElem;
}
 
当我们分析通过直接扩容两倍的方式来分析扩容向量复杂度时,采取的具体尺度是分摊复杂度。
 
所谓分摊复杂度和相关的分摊运行时间,其参与分摊的操作必须构成和来自一个真实可行的操作序列,且足够长。这与传统的平均运行时间有着本质的区别,后者是按照某种假定的概率分布,对各种情况下所需执行时间的加权平均,亦称期望运行时间。
 
对于本文中所采取的两倍扩容操作,所需时间为O(n)。
 
 

以上是关于2.3 动态空间管理的主要内容,如果未能解决你的问题,请参考以下文章

玩转C语言动态内存,轻松管理动态内存空间

一篇文章玩转C语言动态内存,轻松管理动态内存空间

想要节省空间,你必须要知道——动态内存管理(附通讯录动态内存版源码)

剖析c语言动态内存管理

动态内存管理

动态内存管理