QVector与QList

时间:2011-07-06 19:47:04

标签: c++ qt list vector

我有一个我需要迭代的整数列表但是数组不合适。 vectorslists之间有什么区别,在选择类型之前我还需要知道什么?

为了清楚起见,我已经阅读了QT文档,但这是我所知道的程度:

  

QList<T>QLinkedList<T>QVector<T>提供类似的功能。这是一个概述:

     
      
  • 对于大多数用途,QList是正确使用的类。它的基于索引的API比基于QLinkedList's迭代器的API更方便,并且它通常比QVector更快,因为它将其项存储在内存中。它还扩展到可执行文件中的代码更少。
  •   
  • 如果您需要一个真实的链表,并保证在列表中间插入常量时间,并且对项目而不是索引进行迭代,请使用QLinkedList
  •   
  • 如果您希望项目占据相邻的记忆位置,请使用QVector
  •   

5 个答案:

答案 0 :(得分:114)

QVector大致类似于std::vector,正如您可能从名称中猜到的那样。 QList更接近boost::ptr_deque,尽管与std::list明显相关。它不直接存储对象,而是存储指向它们的指针。您可以获得两端快速插入的所有好处,并且重新分配涉及改组指针而不是复制构造函数,但会丢失实际std::dequestd::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::dequestd::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_TYPEQ_PRIMITIVE_TYPE使用   Q_DECLARE_TYPEINFO

     

查看使用QList的优点和缺点   说明。但是,在整个Qt API中使用QList进行传递   参数和返回值。使用QList与这些界面进行交互   的API。

答案 2 :(得分:11)

QVectorstd::vector类似。 QLinkedListstd::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用于大多数用途。

相关问题