我的问题基本上是何时选择QVector
和何时选择QList
作为您的Qt容器。我已经知道的:
For most purposes, QList is the right class to use. Its index-based API is more convenient than QLinkedList's iterator-based API, and it is usually faster than QVector because of the way it stores its items in memory. It also expands to less code in your executable.
QList considered harmful
Don't use QList, use Q_DECLARE_TYPEINFO
据我了解,这种想法是,在堆中分配新元素时,几乎所有类型的
QList
效率都不高。每次添加新元素时,它都会调用new
(每个元素一次),这与QVector
相比效率低下。这就是为什么我现在想要理解的原因:我们应该选择
QVector
作为默认容器吗?
最佳答案
Qt宣传 For most purposes, QList is the right class to use. For most purposes, QList will do.QList
为“万事通”,但那句话的另一半是“无主”。我想说QList
是一个不错的选择,如果您打算追加到列表的两端,并且它们不大于指针,因为QList
前后都保留了空间。就是这样,我的意思是就使用QList
而言,有充分的理由。QList
会自动将“大”对象存储为指针并在堆上分配对象,如果您是婴儿,这不知道如何声明QVector<T*>
并使用动态分配,这可能是一件好事。这不一定是一件好事,在某些情况下,它只会使内存使用量过大,并增加额外的间接访问。 IMO总是明确指出所需的内容(无论是指针还是实例)都是一个好主意。即使您确实希望进行堆分配,也总是最好自己分配它,并简单地将指针添加到列表中,而不是一次构造该对象,然后在堆上进行复制构造。
Qt会在很多地方为您返回QList
,例如在获得QObject
的 child 或您搜索 child 时。在这种情况下,使用在第一个元素之前分配空间的容器是没有意义的,因为它是已经存在的对象的列表,而不是您可能会喜欢的对象。我也不太喜欢缺少resize()
方法。
想象一下这样的情况:在64位系统上,您有一个9字节长且字节对齐的对象。对于QList
来说“太多了”,因此它将使用8字节指针+ CPU开销进行缓慢的堆分配+内存开销进行堆分配。它将使用两倍的内存,并且具有额外的间接访问权限,因此几乎不会像所宣传的那样提供性能优势。
关于QVector
为什么不能突然成为“默认”容器的原因-您不要在赛程中改变马匹-这是一件很古老的事情,Qt是如此旧的框架,即使很多东西已被弃用,也要进行更改并非总是可能使用广泛使用的默认值,并非不破坏大量代码或产生不良行为。无论好坏,QList
在整个Qt 5中都可能一直是默认设置,并且在下一个主要发行版中也可能如此。在智能指针已成为必需品多年之后,并且所有人都在提示普通指针有多糟糕以及如何永远不使用它们之后,Qt将继续使用“哑”指针的原因相同。
话虽这么说,没有人强制您在设计中使用QList
。没有理由不将QVector
设为默认容器。我本人在任何地方都不使用QList
,在返回QList
的Qt函数中,我只是用作将内容移动到QVector
的临时方法。
此外,这只是我个人的观点,但是我确实在Qt中发现了许多不必要的设计决策,例如性能或内存使用效率或明智的易用性,并且总体上有很多框架和喜欢推广自己的做事方式的语言,不是因为这是最好的做事方式,而是因为这是他们做事的方式。
最后但并非最不重要的:
真正归结为您如何理解这一点。国际海事组织在这种情况下,“正确”并不代表“最佳”或“最佳”,而是代表“足够好”,就像“即使不是最佳也可以做到”。特别是如果您对不同的容器类及其工作方式一无所知。
总结一下:QList
专业人士
您打算在
您打算将QVector
与显式指针一起使用,以实现相同且更便宜的方式-无需额外的复制),因为调整列表大小,将不移动任何对象,仅移动指针QList
缺点resize()
方法,reserve()
是一个细微的陷阱,因为它不会增加有效列表的大小,即使索引访问有效,它也属于UB类别,您也将无法迭代该列表
由于最后两个,
CON的优势略大于PRO,这意味着虽然可以“随意”使用QList
,但您绝对不希望在CPU时间和/或内存使用成为关键因素的情况下使用它。总而言之,当您不想为用例考虑最佳存储容器时,QList
最适合懒惰和粗心的使用,通常是QVector<T>
,QVector<T*>
或QLinkedList
(但我排除了“STL“容器,因为我们在这里谈论Qt,所以Qt容器具有可移植性,有时更快,并且最肯定更易于使用和清洁,而std
容器则是不必要的冗长。
关于c++ - 重新访问QList与QVector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33609406/