Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ QList vs QVector重访_C++_Qt_Qt5_Qlist_Qvector - Fatal编程技术网

C++ QList vs QVector重访

C++ QList vs QVector重访,c++,qt,qt5,qlist,qvector,C++,Qt,Qt5,Qlist,Qvector,我的问题基本上是何时选择QVector以及何时选择QList作为您的Qt容器。我已经知道: Qt文档: 在大多数情况下,QList是正确的类。它基于索引的API比QLinkedList基于迭代器的API更方便,而且由于它在内存中存储其项的方式,它通常比QVector更快。它还可以在可执行文件中扩展到更少的代码 同样是这样写的,这是非常流行的问答:。它也支持QList 但是:在最近的2015年Qt世界峰会上,KDAB提出了“为什么QList有害”,基本上是这样的: 据我所知,在堆中分配新元素时

我的问题基本上是何时选择
QVector
以及何时选择
QList
作为您的Qt容器。我已经知道:

  • Qt文档:
  • 在大多数情况下,QList是正确的类。它基于索引的API比QLinkedList基于迭代器的API更方便,而且由于它在内存中存储其项的方式,它通常比QVector更快。它还可以在可执行文件中扩展到更少的代码

  • 同样是这样写的,这是非常流行的问答:。它也支持QList

  • 但是:在最近的2015年Qt世界峰会上,KDAB提出了“为什么QList有害”,基本上是这样的:

  • 据我所知,在堆中分配新元素时,几乎所有类型的
    QList
    都是低效的。每次添加新元素时,它都会调用
    new
    (每个元素调用一次),与
    QVector
    相比,这是效率低下的


    这就是我现在试图理解的原因:我们是否应该选择
    QVector
    作为默认容器?

    QList是作为文档状态一般使用的最佳容器。如果元素类型的大小为sizeof(void*) ===== QList=[4][4][4][4]=新的T*[];//4=指针的大小 | | ... | 新T新T新T新T 如果您希望对象在内存中按顺序排列,而不管其元素的大小,就像OpenGL编程通常的情况一样,那么您应该使用QVector

    下面是QList内部的一个示例

    如果QList的元素类型的大小大于指针的 size QList的性能优于QVector,因为它不存储 对象,但按顺序存储指向堆副本的指针

    我倾向于说相反的话。当检查这些项目时,情况会更糟。 如果它将其存储为堆上的指针,QList的性能不会比QVector差很多吗?顺序存储(QVector一直都是)之所以如此好,是因为它对缓存友好,一旦存储指针,就会丢失数据局部性,开始出现缓存未命中,这对性能非常糟糕

    “默认”容器IMHO应该是QVector(或std::vector),如果您担心大量的重新分配,那么预先分配一个合理的金额,支付一次性成本,从长远来看您将受益


    默认情况下,如果您遇到性能问题,请使用*向量,并根据需要进行配置和更改。

    Qt将
    QList
    宣传为“万事通”,但这句话的另一半是“一无是处”。如果您计划在列表的两端追加内容,那么我认为
    QList
    是一个很好的选择,因为
    QList
    在列表前后都保留了空间,所以列表的两端都不超过一个指针。就是这样,我的意思是,就使用
    QList
    的充分理由而言

    QList
    将自动将“大型”对象存储为指针,并在堆上分配对象,如果您是婴儿,这可能被认为是一件好事,因为婴儿不知道如何声明
    QVector
    并使用动态分配。这不一定是件好事,在某些情况下,它只会增加内存使用量并增加额外的间接寻址。在我看来,明确你想要什么总是一个好主意,不管是指针还是实例。即使您确实想要堆分配,也最好自己分配,并简单地将指针添加到列表中,而不是构造一次对象,然后在堆上进行复制构造

    Qt会在很多地方返回一个
    QList
    ,这会带来开销,例如在获取
    QObject
    的子对象或搜索子对象时。在这种情况下,使用在第一个元素之前分配空间的容器是没有意义的,因为它是一个已经存在的对象列表,而不是您可能预先准备的对象。我也不太喜欢缺少
    resize()
    方法

    想象一下,在64位系统上有一个大小为9字节、字节对齐的对象。对于
    QList
    来说,它“太多了”,因此它将使用8字节指针+CPU开销进行缓慢的堆分配+内存开销进行堆分配。它将使用两倍的内存和额外的间接访问,它几乎不会提供广告中所宣传的性能优势

    至于为什么
    QVector
    不能突然成为“默认”容器-你不会中途更改马-这是一个遗留的东西,Qt是一个如此古老的框架,尽管很多东西已经被弃用,但对广泛使用的默认值进行更改并不总是可能的,不是不破坏很多代码,或者产生不想要的行为。无论好坏,
    QList
    很可能在整个Qt5中一直是默认的,也可能在下一个主要版本中。同样的原因是,Qt将继续使用“哑”指针,在智能指针成为必须的东西之后的几年里,每个人都在为普通指针有多糟糕以及如何永远不要使用它们而哭泣

    也就是说,没有人强迫您在设计中使用
    QList
    。没有理由不将
    QVector
    作为默认容器。我自己在任何地方都不使用
    QList
    ,在返回
    QList
    的Qt函数中,我只是将内容临时移动到
    QVector

    此外,这只是我个人的观点,但我确实发现Qt中的许多设计决策没有必要有意义,无论是性能还是内存使用效率还是易用性,总体而言,有很多框架和语言喜欢推广他们的做事方式,不是因为这是最好的方式,但因为这是他们的方式

    最后但并非最不重要的是:

    对于大多数p
    sizeof( T ) <= sizeof( void* )
    =====
    QList< T > = [1][1][1][1][1]
                       or
                 [2][2][2][2][2]
                       or
                 [3][3][3][3][3]
                       or
                 [4][4][4][4][4] = new T[];
    
    sizeof( T ) > sizeof( void* )
    =====
    QList< T > = [4][4][4][4][4] = new T*[]; // 4 = pointer's size
                  |   |  ...  |
               new T new T   new T
    
    // QVector<DataType> internal structure
    DataType* pArray = new DataType[100];
    
    // QList<DataType> internal structure
    DataType** pPointersArray = new DataType*[100];
    
    {
    // ...
    cout << pArray[index]; //fast
    cout << *pPointersArray[index]; //slow, need additional operation for dereferencing
    // ...
    }
    
    {
    // QVector swaping
    DataType copy = pArray[index];
    pArray[index] = pArray[index + 1];
    pArray[index + 1] = copy; // copy object
    
    // QList swaping
    DataType* pCopy = pPointersArray [index];
    pPointersArray[index] = pPointersArray [index + 1];
    pPointersArray[index + 1] = pCopy; // copy pointer
    // ...
    }
    
    [ | | | | | | | [ | | | | | | | [ ...
    [b|   padding   [b|   padding   [b...