首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么QList没有resize()方法呢?

为什么QList没有resize()方法呢?
EN

Stack Overflow用户
提问于 2013-02-04 16:47:37
回答 3查看 15.1K关注 0票数 13

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

EN

回答 3

Stack Overflow用户

发布于 2013-02-04 20:59:23

好吧,这是更通用的答案,但我希望通过比较QListQVector,你会明白为什么不需要手动扩展容器。

QList使用内部缓冲区来保存指向元素的指针(或者,如果元素小于指针大小,或者元素本身是shared classes元素之一),则实际数据将保存在堆中。

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

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

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

然而,这是有代价的,这意味着你有时会更喜欢QVector而不是QList:对于存储在QList中的单个项,您需要在堆上额外分配一个空间-以保存该项的实际数据(内部缓冲区中指针所指向的数据)。如果要添加比指针大10000个项(因为,如果指针适合指针,它将直接存储在内部缓冲区中),则需要10000个系统调用来为堆上的10000个项分配数据。但是,如果您使用的是QVector,并且您调用了resize,那么您能够在单个alloc调用中容纳所有项-因此,如果您需要大量的插入或附加操作,请不要使用QList,最好使用QVector。当然,如果您使用QList来存储共享类,则不需要额外的分配,这再次使QList更合适。

因此,在大多数情况下,最好使用QList

使用索引来访问单个元素,访问项将比QLinkedList

  • Inserting到列表中间只需要移动指针来创建空间要快,而且比移动实际的QVector数据快不需要手动保留空间或调整空间大小around.

  • There不需要手动保留空间或调整空间大小,因为空白空间将移动到缓冲区的末尾以供以后使用,并且在数组中分配空间非常快,因为元素非常小,并且它可以分配大量空间,而不会占用内存空间。

请不要在以下场景中使用它,最好使用QVector

如果您需要确保您的数据存储在顺序的内存位置

  • 如果您很少在随机位置插入数据,但您在结尾或开头追加了很多数据,这可能会导致许多不必要的系统调用,并且您仍然需要快速索引。如果您正在为不会随时间增长的简单阵列寻找(共享的)替代方案,请使用

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

票数 10
EN

Stack Overflow用户

发布于 2017-05-18 01:09:05

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

代码语言:javascript
运行
复制
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());
}

如果不使用智能指针,下面的代码会将不同的对象添加到您的列表中。

代码语言:javascript
运行
复制
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());
}

还要记住,你的对象必须有默认的构造函数(在头文件中用arg=“someValue”声明的构造函数),否则它将失败。

票数 0
EN

Stack Overflow用户

发布于 2016-01-28 05:40:43

只需使用类似于

代码语言:javascript
运行
复制
QList<Smth> myList;
// ... some operations on the list here
myList << QVector<Smth>(desiredNewSize - myList.size()).toList();

本质上,到处都有这些to/from Vector/List/Set()方法,这使得在必要时以某种手动的方式调整Qt容器的大小变得微不足道,但我相信是微不足道和有效的方式。

另一种(单线性或双线性)解决方案是:

代码语言:javascript
运行
复制
myList.reserve(newListSize); // note, how we have to reserve manually
std::fill_n(std::back_inserter(myList), desiredNewSize - myList.size(), Smth());

--这是针对面向STL的人员的:)

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

票数 -3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14683161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档