C++ deque::收缩内存以适应内存保证
由于内存要求很紧,所以在从deque开头删除一个范围后,我试图使用C++ deque::收缩内存以适应内存保证,c++,c++11,deque,C++,C++11,Deque,由于内存要求很紧,所以在从deque开头删除一个范围后,我试图使用deque::shrink_to_fit。但是,它不起作用,我只是看到libstdc++使用交换技巧和副本实现了shrink\u to\u fit。这实际上意味着,不是更好的内存使用率,而是我在一段时间内得到了2倍的使用率,并因此受到了限制 我认为这限制了shrink\u to\u fit的可用性,我想知道标准中是否有任何保证?我在草稿副本(N3035)中查找它,只看到“这是一个无约束力的请求…”。我知道为什么它是非绑定的,也知道
deque::shrink_to_fit
。但是,它不起作用,我只是看到libstdc++使用交换技巧和副本实现了shrink\u to\u fit
。这实际上意味着,不是更好的内存使用率,而是我在一段时间内得到了2倍的使用率,并因此受到了限制
我认为这限制了
shrink\u to\u fit
的可用性,我想知道标准中是否有任何保证?我在草稿副本(N3035)中查找它,只看到“这是一个无约束力的请求…”。我知道为什么它是非绑定的,也知道为什么它不能用于vector
,但从我对deque
实现的了解来看,应该可以提供一些内存保证(看看libc++,它似乎是以一种更智能的方式实现的)。因为它们与特定的实现相关,所以没有任何保证吗?的libstdc++和libc++实现都符合我的要求。但是它们非常不同,主要是因为这两个实现遵循不同的类不变量
首先,对于那些不知道的人来说,std::deque
是指向固定大小的t
数组的指针数组(通常是t*
,但自定义分配器可以将其推广)。指针数组可以被视为一个循环缓冲区,也可以被视为一个可以将其数据的开头从缓冲区的开头滑出的缓冲区
这个答案将只关注deque的固定长度数组
libstdc++
libstdc++实现有一个不变量,即deque
中从来没有空数组。如果pop_front
或pop_back
创建了一个空数组,则该数组在擦除过程中被释放。这种设计减少了deque::shrink_to_fit
实际可以实现的功能,因为deque
始终处于或非常接近最小内存占用
libstdc++shorn_to_fit
仅当它能够证明自己可以通过这样做来消除数组时,才会执行复制和交换。例如,deque
可以保存1010个值,由三个固定长度数组支持,每个数组的容量为1000个值。deque
中的第一个元素可能从第一个数组中的995位置开始。因此,第一个和第三个数组中的大多数(但不是全部)是空的。复制/交换将分配两个新数组,将1010个元素复制/移动到这两个数组中,然后取消分配旧的3个数组
libc++
libc++实现采用了一种略微不同的设计,旨在提高速度。当pop_front
(或pop_back
)清空一个数组时,除非前面(或后面)已经有一个空数组,否则该数组不会被释放。也就是说,虽然libstdc++不变量表示在整个deque
中从来没有空数组,但libc++不变量表示在deque
的前后可以有零个或一个空数组。这样做的基本原理是,如果push_-back
(或push_-front
)需要一个新数组,它首先在deque
的另一端寻找一个空数组,然后再从那里开始分配一个新数组。给定一个大小大致恒定的FIFO队列,此设计将达到这样的状态:pop\u front
/push\u back
序列将永远不会分配新数组。相反,数组从deque
的前面循环到后面(反之亦然)
libc++shorn_to_fit
将丢弃deque
两端的空数组(如果存在)。相反,libstdc++不需要这样做,因为空数组永远不存在。libc++通过复制/交换操作将值移近块的开头,从而缩小内存占用,但libc++不会尝试进一步减少内存占用
结果是,libc++收缩到适应
不会使引用无效,而libstdc++收缩到适应
通常会使引用无效。请注意,shrink\u to\u fit
的规范旨在允许引用无效,尽管现在我看,我认为它错误地不允许(对于vector::shrink\u to\u fit
,必须这样做,deque
的措词取自vector
的措词)
这两种实现还将缩小以适应T*
的底层缓冲区,尽管这有相对较小的影响,因为T*
的缓冲区的内存占用通常比阵列的内存占用小得多。每个libc++数组通常占用4096字节(1页),而每个libstdc++数组通常占用512字节
我不知道VC++deque做什么。但它也将实现一个数组数组
正如我们所看到的,虽然所有实现都在相同的数据结构上运行(以符合复杂性和无效性要求),但仍有一些重要的设计决策留给实现,每个实现都努力提供它认为最适合其客户的产品。您所说的“它不起作用”?我指的是第一段的最后一句话。与其提高内存使用率,shorn\u to\u fit
将其增加了两倍,并导致我的进程被阻塞(是的,我知道,我使用的内存太多了).您如何看待将内存使用率缩小到原来的两倍?您的编译器是什么?如果是这样的话,那么它是一个bug…您在deque
中存储了什么类型的项?感谢您的详细解释。我认为deque与vector类似,它从不返回分配的内存(尽管现在我认为