Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't QList have a resize() method?

Tags:

c++

qt

qlist

I just noticed that QList doesn't have a resize method, while QVector, for example, has one. Why is this? And is there an equivalent function?

like image 665
sashoalm Avatar asked Feb 04 '13 08:02

sashoalm


1 Answers

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 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.

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.

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. 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.

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). 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. 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. Of course, if you are using QList to store shared classes, there is no need for additional allocating, which again makes QList more suitable.

So, prefer QList for most of the cases as it is:

  1. Using indices to access the individual elements, accessing items will be faster that QLinkedList
  2. Inserting into middle of the list will only require moving of the pointers to create space, and it is faster than shifting actual QVector data around.
  3. There is no need to manually reserve or resize space, as empty space will be moved to the end of the buffer for later use, and allocating space in the array is very fast, as the elements are very small, and it can allocate a lot of space without killing your memory space.

Don't use it in the following scenarios, and prefer QVector:

  1. If you need to ensure that your data is stored in the sequential memory locations
  2. If you are rarely inserting data at the random positions, but you are appending a lot of data at the end or beginning, which can cause a lot of unnecessary system calls, and you still need fast indexing.
  3. If you are looking for (shared) replacement for simple arrays which will not grow over the time.

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. However, this will not affect external size of the QList (size() will always return the exact number of elements contained in the list).

like image 189
Nemanja Boric Avatar answered Sep 30 '22 18:09

Nemanja Boric