C++ 为什么';t QList是否有resize()方法?

C++ 为什么';t QList是否有resize()方法?,c++,qt,qlist,C++,Qt,Qlist,我刚刚注意到QList没有resize方法,而QVector有一个方法。为什么会这样?还有一个等价的函数吗?好吧,这是更一般的答案,但我希望通过比较QList和QVector可以看出为什么不需要手动扩展容器 QList使用内部缓冲区保存指向元素的指针(或者,如果元素小于指针大小,或者元素本身是-元素之一),并且实际数据将保留在堆上 在此期间,删除数据不会减少内部缓冲区(空空间将通过向左或向右移动元素来填充,在开始和结束处留出空间供以后插入) 附加项,如QVector,将在数组的末尾创建额外的新空

我刚刚注意到
QList
没有
resize
方法,而
QVector
有一个方法。为什么会这样?还有一个等价的函数吗?

好吧,这是更一般的答案,但我希望通过比较
QList
QVector
可以看出为什么不需要手动扩展容器

QList使用内部缓冲区保存指向元素的指针(或者,如果元素小于指针大小,或者元素本身是-元素之一),并且实际数据将保留在堆上

在此期间,删除数据不会减少内部缓冲区(空空间将通过向左或向右移动元素来填充,在开始和结束处留出空间供以后插入)

附加项,如
QVector
,将在数组的末尾创建额外的新空间,并且由于与
QVector
不同,真实数据不存储在内部缓冲区中,所以无论项的大小如何,您都可以在单个指令中创建大量的空间(与
QVector
不同)-因为您只是将指针添加到索引缓冲区中

例如,如果您使用32位系统(每个指针4个字节),并且在
QList
中存储50个项目,并且每个项目都有1MB大,
QVector
缓冲区需要调整为50MB,而
QList
的内部缓冲区只需要分配200B内存。这是您需要在
QVector
中调用
resize()
的地方,但是在
QList
中没有必要调用,因为分配小内存块与分配50MB内存一样没有问题

然而,这是有代价的,这意味着您有时需要预先输入
QVector
而不是
QList
:对于存储在
QList
中的单个项,您需要在堆上添加一个alloc,以保留项的真实数据(内部缓冲区中指针指向的数据)。如果您想添加比指针大10000个项目(因为,如果它可以放入指针,它将直接存储在内部缓冲区中),则需要10000个系统调用来为堆上的10000个项目分配数据。但是,如果您使用
QVector
,并调用
resize
,则可以在单个alloc调用中容纳所有项目-因此,如果您需要大量插入或追加,请不要使用
QList
,最好使用
QVector
。当然,如果您使用
QList
存储共享类,则不需要额外分配,这同样使
QList
更合适

因此,对于大多数情况,请选择
QList

  • 使用索引访问单个元素,访问项目的速度将快于
    QLinkedList
  • 插入到列表中间只需要移动指针来创建空间,而且比移动实际的
    QVector
    数据要快
  • 无需手动保留或调整空间大小,因为空空间将移动到缓冲区的末尾以供以后使用,并且在数组中分配空间非常快,因为元素非常小,而且它可以分配大量空间而不会占用内存空间
  • 不要在以下情况下使用它,而更喜欢
    QVector

  • 如果您需要确保数据存储在顺序存储器位置中
  • 如果您很少在随机位置插入数据,但添加了大量数据 在末尾或开头,这可能会导致大量不必要的系统调用,并且仍然需要快速索引
  • 如果您正在寻找(共享)简单阵列的替代品,这些阵列将不会随着时间的推移而增长

  • 最后,请注意:
    QList
    (和
    QVector
    )具有
    reserve(intalloc)
    功能,如果
    alloc
    大于内部缓冲区的当前大小,则会导致
    QList
    的内部缓冲区增长。但是,这不会影响
    QList
    的外部大小(
    size()
    将始终返回列表中包含的元素的确切数量)。

    我认为原因是
    QList
    不要求元素类型具有默认构造函数。 因此,在
    QList
    创建对象时,不存在任何操作,而只复制对象

    但是,如果您确实需要调整
    QList
    (无论出于何种原因),这里有一个函数可以做到这一点。请注意,它只是一个方便的函数,编写时并没有考虑性能

    模板
    void resizeList(QList&list,int newSize){
    int diff=newSize-list.size();
    T;
    如果(差异>0){
    列表.储备(差异);
    while(diff--)list.append(t);
    }else如果(diff<0)list.erase(list.end()+diff,list.end());
    }
    
    只要使用

    QList<Smth> myList;
    // ... some operations on the list here
    myList << QVector<Smth>(desiredNewSize - myList.size()).toList();
    
    --这是面向STL的人的:)

    有关有效的
    QList::resize()
    可能会有多复杂的背景信息,请参阅:

    • ,及

      • wasle答案很好,但它会多次添加同一对象。下面是一个实用函数,它将为智能指针列表添加不同的对象

        template<class T>
        void resizeSmartList(QList<QSharedPointer<T> > & list, int newSize) {
            int diff = newSize - list.size();
        
            if (diff > 0) {
                list.reserve(diff);
                while (diff>0){
                    QSharedPointer<T> t = QSharedPointer<T>(new T);
                    list.append(t);
                    diff--;
                }
            }else if (diff < 0) list.erase(list.end() + diff, list.end());
        }
        
        模板
        void resizeSmartList(QList&list,int newSize){
        int diff=newSize-list.size();
        如果(差异>0){
        列表.储备(差异);
        而(差异>0){
        QSharedPointer t=QSharedPointer(新t);
        列表。追加(t);
        差异--;
        }
        }else如果(diff<0)list.erase(list.end()+diff,list.end());
        }
        
        如果不使用智能指针,下面将向列表中添加不同的对象

        template<class T>
        void resizeList(QList<T> & list, int newSize) {
            int diff = newSize - list.size();
        
            if (diff > 0) {
                list.reserve(diff);
                while (diff>0){
                    T t = new T;
                    list.append(t);
                    diff--;
                }
            }else if (diff < 0) list.erase(list.end() + diff, list.end());
        }
        
        模板
        void resizeList(QList&list,int newSize){
        int diff=newSize-list.size();
        如果(差异>0){
        列表.储备(差异);
        而(差异>0){
        
        template<class T>
        void resizeSmartList(QList<QSharedPointer<T> > & list, int newSize) {
            int diff = newSize - list.size();
        
            if (diff > 0) {
                list.reserve(diff);
                while (diff>0){
                    QSharedPointer<T> t = QSharedPointer<T>(new T);
                    list.append(t);
                    diff--;
                }
            }else if (diff < 0) list.erase(list.end() + diff, list.end());
        }
        
        template<class T>
        void resizeList(QList<T> & list, int newSize) {
            int diff = newSize - list.size();
        
            if (diff > 0) {
                list.reserve(diff);
                while (diff>0){
                    T t = new T;
                    list.append(t);
                    diff--;
                }
            }else if (diff < 0) list.erase(list.end() + diff, list.end());
        }