[英]Why doesn't QList have a resize() method?
I just noticed that QList
doesn't have a resize
method, while QVector
, for example, has one.我只是注意到
QList
没有resize
方法,而QVector
,例如,有一个。 Why is this?为什么是这样? And is there an equivalent function?
是否有等效的功能?
Well, this is the more generic answer, but I hope you will see, by comparising QList
and QVector
why there is no need of manually expanding the container.嗯,这是更通用的答案,但我希望您通过比较
QList
和QVector
明白为什么不需要手动扩展容器。
QList is using internal buffer to save pointers to the elements (or, if the element is smaller than pointer size, or element is one of the shared classes - elements itself), and the real data will be kept on the heap. QList 使用内部缓冲区来保存指向元素的指针(或者,如果元素小于指针大小,或者元素是共享类之一- 元素本身),真实数据将保存在堆上。
During the time, removing the data will not reduce internal buffer (empty space will be filled by shifting left or right elements, leaving space on the beginning and the end for later insertions).在此期间,删除数据不会减少内部缓冲区(将通过向左或向右移动元素来填充空白空间,在开头和结尾留出空间供以后插入)。
Appending items, like QVector
will create additional new space on end of the array, and since, unlike QVector
, real data is not stored in internal buffer, you can create a lot of space in single instruction, no matter what size of the item is (unlike QVector
) - because you are simply adding pointers into indexing buffer.附加项目,如
QVector
将在数组末尾创建额外的新空间,并且由于与QVector
不同,真实数据不存储在内部缓冲区中,因此无论项目的大小如何,您都可以在单个指令中创建大量空间(与QVector
不同) - 因为您只是将指针添加到索引缓冲区中。
For example, if you are using 32bit system (4 bytes per pointer) and you are storing 50 items in the QList
, and each item is 1MB big, QVector
buffer will need to be resized to 50MB, and QList
's internal buffer is need to allocate only 200B of memory.例如,如果您使用 32 位系统(每个指针 4 个字节)并且您在
QList
中存储 50 个项目,并且每个项目有 1MB 大,则QVector
缓冲区将需要调整为 50MB,并且需要QList
的内部缓冲区只分配 200B 的内存。 This is where you need to call resize()
in QVector
, but in QList
there is no need, since allocating small chunk of memory is not problematic, as allocating 50MB of memory.这是您需要在
QVector
调用resize()
的QVector
,但在QList
中则不需要,因为分配小块内存没有问题,因为分配 50MB 内存。
However, there is a price for that which means that you sometimes you want to preffer QVector
instead of QList
: For single item stored in the QList
, you need one additional alloc on the heap - to keep the real data of the item (data where pointer in the internal buffer is pointing to).但是,这样做是有代价的,这意味着您有时想要
QVector
而不是QList
:对于存储在QList
中的单个项目,您需要在堆上进行一个额外的分配 - 以保留项目的真实数据(数据在哪里内部缓冲区中的指针指向)。 If you want to add 10000 items larger than the pointer (because, if it can fit into pointer, it will be stored directly in the internal buffer), you will need 10000 system calls to allocate data for 10000 items on the heap.如果要添加大于指针的 10000 个项目(因为,如果它可以装入指针,它将直接存储在内部缓冲区中),您将需要 10000 次系统调用来为堆上的 10000 个项目分配数据。 But, if you are using
QVector
, and you call resize
, you are able to fit all the items in the single alloc call - so don't use QList
if you need a lot of inserting or appending, prefer QVector
for that.但是,如果您使用
QVector
并调用resize
,则可以在单个 alloc 调用中容纳所有项目 - 因此,如果您需要大量插入或附加,请不要使用QList
,因此更喜欢QVector
。 Of course, if you are using QList
to store shared classes, there is no need for additional allocating, which again makes QList
more suitable.当然,如果你使用
QList
来存储共享类,则不需要额外的分配,这再次使QList
更适合。
So, prefer QList
for most of the cases as it is:因此,在大多数情况下更喜欢
QList
,因为它是:
QLinkedList
QLinkedList
更快QVector
data around.QVector
数据更快。 Don't use it in the following scenarios, and prefer QVector
:不要在以下场景中使用它,而更喜欢
QVector
:
And, finally, note: QList
(and QVector
) have reserve(int alloc)
function which will cause QList
's internal buffer to grow if alloc
is greater than the current size of the internal buffer.最后,请注意:
QList
(和QVector
)具有reserve(int alloc)
函数,如果alloc
大于内部缓冲区的当前大小,它将导致QList
的内部缓冲区增长。 However, this will not affect external size of the QList
( size()
will always return the exact number of elements contained in the list).但是,这不会影响
QList
外部大小( size()
将始终返回列表中包含的元素的确切数量)。
I think reason is because QList
doesn't require the element type to have a default constructor.我认为原因是因为
QList
不需要元素类型具有默认构造函数。 As a result of this, there is no operation where QList
ever creates an object it only copies them.因此,没有任何操作可以让
QList
创建一个只复制它们的对象。
But if you really need to resize a QList
(for whatever reason), here's a function that will do it.但是如果你真的需要调整
QList
大小(无论出于何种原因),这里有一个函数可以做到。 Note that it's just a convenience function , and it's not written with performance in mind .请注意,它只是一个方便的函数
,并没有考虑到性能。
template<class T>
void resizeList(QList<T> & list, int newSize) {
int diff = newSize - list.size();
T t;
if (diff > 0) {
list.reserve(newSize);
while (diff--) list.append(t);
} else if (diff < 0) list.erase(list.end() + diff, list.end());
}
wasle answer is good, but it'll add the same object multiple time. wasle 答案很好,但它会多次添加相同的对象。 Here is an utility functions that will add different object for list of smart pointers.
这是一个实用函数,它将为智能指针列表添加不同的对象。
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());
}
For use without smart pointers, the following will add different objects to your list.为了在没有智能指针的情况下使用,以下内容会将不同的对象添加到您的列表中。
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());
}
Also remember that your objects must have default constructor (constructor declared in the header with arg="someValue") or else it will fail.还请记住,您的对象必须具有默认构造函数(在标头中使用 arg="someValue" 声明的构造函数),否则它将失败。
Just use something like只需使用类似的东西
QList<Smth> myList;
// ... some operations on the list here
myList << QVector<Smth>(desiredNewSize - myList.size()).toList();
Essentially, there are these to
/ from
Vector
/ List
/ Set()
methods everywhere, which makes it trivial to resize Qt containers when necessary in a somewhat manual, but trivial and effective (I believe) way.本质上,到处都有这些
to
/ from
Vector
/ List
/ Set()
方法,这使得在必要时以某种手动但微不足道且有效(我相信)的方式调整 Qt 容器的大小变得微不足道。
Another (1 or 2-liner) solution would be:另一种(1 或 2 线)解决方案是:
myList.reserve(newListSize); // note, how we have to reserve manually
std::fill_n(std::back_inserter(myList), desiredNewSize - myList.size(), Smth());
-- that's for STL-oriented folks :) -- 那是给面向 STL 的人的 :)
For some background on how complex an effective QList::resize()
may get, see:有关有效
QList::resize()
可能变得多么复杂的一些背景,请参阅:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.