想知道为什么我的内存访问速度比我预期的慢一些,我终于发现deque
的Visual C ++实现确实有一个内置的间接额外层,摧毁了我的记忆地点。</ p>
即。它似乎包含T*
的数组,而不是T
的数组。
我可以在VC ++中使用另一个没有这个“功能”的实现,还是有某种方法(虽然我认为不太可能)在这个实现中能够避免它?
我基本上正在寻找一个前面也有O(1)推/弹的vector
。
我想我可以自己实现它,但是处理allocator
等等是很痛苦的,需要一段时间才能做到正确,所以我宁愿使用之前编写/测试过的东西。
答案 0 :(得分:10)
无论出于何种原因,至少从MSVC 2010开始,std::deque
实现似乎使用了一个令人难以置信的小块大小(如果我没弄错的话,最多16个字节或1个单个元素!)。
根据我的经验,这可能会导致非常严重的性能问题,因为数据结构中的每个“块”基本上只会存储单个元素,从而导致各种额外开销(时间和内存)。 / p>
我不知道为什么这样做。据我了解,设置deque
具有如此小的块大小正是它不应该如何完成。
查看gcc stdlib
实施。从内存中他们使用更大的块大小。
编辑:试图解决其他问题:
std::deque
应该有一个额外的间接层。它通常被实现为“被阻止的”数据结构 - 即存储“节点”的数组,其中每个节点本身是数据元素的数组。它不像链接列表 - 节点数组永远不会像列表那样“遍历”,它总是直接编入索引(即使每个块有1个元素)。
当然,您可以滚动自己的数据结构,在前面留出一些额外的空间。它不会有最坏的O(1) push/pop front/back
行为,因此它不会满足std::deque
容器的要求。但如果你不关心任何......
答案 1 :(得分:2)
C ++标准不允许std::deque
在向前或向后推送时重新分配。这些操作始终是恒定的时间。不摊销,始终。
C ++标准没有这样的容器。根据我的知识,Boost没有一个(想到Boost.Container库可能;我没有考虑过它。)
答案 2 :(得分:0)
您抱怨的间接实际上是强制标准要求,引用/指针永远不会被push
/ pop
front
/ {{1 (显然除了那些引用/指向被删除元素的指针)。
所以你看到这个要求与任何复杂性要求无关。
当没有可用空间时,此间接还允许更快(但仍为O(大小))back
push
/ front
。