我有一个我需要迭代的整数列表但是数组不合适。
vectors
和lists
之间有什么区别,在选择类型之前我还需要知道什么?
为了清楚起见,我已经阅读了QT文档,但这是我所知道的程度:
QList<T>
,QLinkedList<T>
和QVector<T>
提供类似的功能。这是一个概述:
- 对于大多数用途,
QList
是正确使用的类。它的基于索引的API比基于QLinkedList's
迭代器的API更方便,并且它通常比QVector
更快,因为它将其项存储在内存中。它还扩展到可执行文件中的代码更少。- 如果您需要一个真实的链表,并保证在列表中间插入常量时间,并且对项目而不是索引进行迭代,请使用
QLinkedList
。- 如果您希望项目占据相邻的记忆位置,请使用
QVector
。
答案 0 :(得分:114)
QVector
大致类似于std::vector
,正如您可能从名称中猜到的那样。 QList
更接近boost::ptr_deque
,尽管与std::list
明显相关。它不直接存储对象,而是存储指向它们的指针。您可以获得两端快速插入的所有好处,并且重新分配涉及改组指针而不是复制构造函数,但会丢失实际std::deque
或std::vector
的空间局部性,并获得大量堆分配。它确实有一些决策可以避免小对象的堆分配,重新获得空间局部性,但据我所知它只适用于小于int
的东西。
QLinkedList
类似于std::list
,并且具有它的所有缺点。一般来说,这应该是您最后选择的容器。
QT库非常倾向于使用QList
个对象,因此在您自己的代码中使用它们有时可以避免一些不必要的乏味。在某些情况下,额外的堆使用和实际数据的随机定位在理论上可能会受到伤害,但通常是不可察觉的。所以我建议使用QList
,直到分析建议更改为QVector
。如果您希望连续分配很重要[请参阅:您正在与需要T[]
而不是QList<T>
的代码进行交互,这也可能是开始QVector
关闭的理由蝙蝠。
如果您一般询问容器,并且仅使用QT文档作为参考,那么上述信息就不那么有用了。
std::vector
是一个可以调整大小的数组。所有元素彼此相邻存储,您可以快速访问各个元素。缺点是插入只在一端有效。如果你把东西放在中间或开头,你必须复制其他对象以腾出空间。在大写符号中,最后插入是O(1),其他地方的插入是O(N),随机访问是O(1)。
std::deque
类似,但不保证对象彼此相邻存储,并允许两端插入为O(1)。它还需要一次分配较小的内存块,这有时很重要。随机访问是O(1),中间插入是O(N),与vector
相同。空间位置比std::vector
差,但物体往往聚集在一起,因此您可以获得一些好处。
std::list
是链接列表。它需要三个标准顺序容器的最大内存开销,但可以在任何地方快速插入...前提是您事先知道需要插入的位置。它不提供对单个元素的随机访问,因此您必须迭代O(N)。但是一旦那里,实际插入是O(1)。 std::list
的最大好处是可以快速将它们拼接在一起......如果将整个值范围移动到不同的std::list
,则整个操作为O(1)。使列表中的引用无效也更加困难,这有时很重要。
作为一般规则,我更喜欢std::deque
到std::vector
,除非我需要能够将数据传递给需要原始数组的库。 std::vector
保证是连续的,因此&v[0]
可用于此目的。我不记得上一次使用std::list
了,但几乎可以肯定,因为我需要更强大的关于引用仍然有效的担保人。
答案 1 :(得分:39)
事情发生了变化
我们现在在Qt 5.8中,事情发生了变化,所以文档也是如此。它为这个问题提供了一个清晰而不同的答案:
QVector
应该是您默认的首选。通常QVector<T>
提供比QList<T
&gt;更好的性能,因为QVector<T>
总是如此 将其项目按顺序存储在内存中,QList<T>
将分配 除非sizeof(T) <= sizeof(void*)
和T已经存在,否则它在堆上的项目 声明为Q_MOVABLE_TYPE
或Q_PRIMITIVE_TYPE
使用Q_DECLARE_TYPEINFO
。查看使用
QList
的优点和缺点 说明。但是,在整个Qt API中使用QList
进行传递 参数和返回值。使用QList
与这些界面进行交互 的API。
答案 2 :(得分:11)
QVector
与std::vector
类似。 QLinkedList
与std::list
类似。 QList
是一个基于索引的向量,但不保证内存位置(如std::deque
)。
答案 3 :(得分:2)
来自QtList doc:
在大多数情况下使用QList。对于具有数千个项目的结构,可以在中间有效插入,并提供索引访问。 prepend()
和append()
非常快,因为内存在内部数组的两端预先分配。 QList<T>
是类型为T的指针数组。如果T具有指针或类似Qt共享的指针类型,则对象直接存储在数组中
QVector
在大量append()
或insert()
个新项目大小超过指针的情况下首选QVector
为其分配内存单个堆分配中的项目。对于QList
,插入新项目的附加内容需要在堆上对新项目进行内存分配。简而言之,如果您希望项目占用相邻的内存位置,或者您的项目大于指针,并且您希望避免在插入时单独在堆上分配它们的开销,则使用QVector
。< / p>
答案 4 :(得分:-2)
QVector
就像一个可以改变大小(增加或减少)的数组,但它带来了繁重的事务,计算和时间。
例如,如果要添加项目,则会创建一个新数组,将所有项目复制到新数组,将新项目添加到末尾,并删除旧数组。反之亦然。
但是,QLinkedList
适用于指针。因此,当创建新项目时,只分配一个新的内存空间并链接到唯一的内存块。由于它适用于指针,因此速度更快,效率更高。
如果您有不希望更改大小的项目列表,QVector
可能很好,但通常QLinkedList
用于大多数用途。