标签:适用于 共享 ash c++ play 记录 hash 算法 内存分配器
在QT的Reference中无意看到了QString及其他类型数据结构内存的分配策略,翻译并记录一下。
在QString的数据结构中,QString通过一次附加一个字符来动态构建字符串。假设我们向QString字符串追加15000个字符。然后,当QString空间不足时,会发生以下18个重新分配的过程(假设目前有15000个字符):
4,8,12,16,20,52,116,244,500,1012,2036,4084,6132,8180,10228, 12276、14324、16372
最后,QString分配了16372个Unicode字符,其中15000个被占用。
上面的内存分配状况看起来比较奇怪,以下是内存分配原则:
1、QString一次分配4个字符,直到达到大小20。
2、从20到4084,每次将大小增加一倍。更准确地说,它的内存分配量扩大到2的下一个乘方数减去12。(某些内存分配器在要求精确的2的乘方数时表现最差,因为它们每个块还需要使用额外的几个字节进行记录。)
3、从4084开始,每次分配2048个字符(4096字节)的内存块。因为现代操作系统在重新分配缓冲区时不会复制整个数据。只需简单地对物理内存页面进行重新排序,并且实际上只需要复制首页和最后一页上的数据。
QByteArray和QList <T>使用与QString大致相同的算法。
QVector <T>还将该算法用于可以使用memcpy()在内存中移动的数据类型(包括基本的C++类型,指针类型和Qt的共享类),但对只能用于通过调用复制构造函数和析构函数进行移动。由于在这种情况下重新分配的成本较高,因此QVector <T>在空间不足时,始终通过将内存翻倍来减少重新分配的次数。
QHash <Key,T>是完全不同的情况。 QHash的内部哈希表以2的幂次方增长,并且每次增长时,这些项都将重新放置在新的存储桶中,计算方式为qHash(key)%QHash::capacity()(存储桶数)。此注释也适用于QSet <T>和QCache <Key,T>。
对于大多数应用程序,Qt提供的默认增长算法可以解决问题。如果需要更多控制,QVector <T>,QHash <Key,T>,QSet <T>,QString和QByteArray提供了三个函数,可让您检查并指定用于存储项目的内存量:
1、Capacity()返回为其分配内存的项目数(对于QHash和QSet,为哈希表中的存储桶数)。
2、reserve(size)显式预分配大小项目的内存。
3、squeeze()释放不需要存储项目的任何内存。
如果在一开始就知道一个容器中存储大约多少个项目,则可以通过调用reserve()将内存分配完成,减少过程中不必要的内存分配,并在完成容器的填充后,可以调用squeeze()释放额外的预分配内存。
标签:适用于 共享 ash c++ play 记录 hash 算法 内存分配器
原文地址:https://www.cnblogs.com/Meong/p/13080102.html