PDA

View Full Version : Qt 4.6.3 QByteArray reserve does't influence resize behavior



AnatolyS
21st August 2010, 10:32
Hi!
According to this part of documentation:

void QByteArray::reserve ( int size )
Attempts to allocate memory for at least size bytes. If you know in advance how large the byte array will be, you can call this function, and if you call resize() often you are likely to get better performance. If size is an underestimate, the worst that will happen is that the QByteArray will be a bit slower.

The sole purpose of this function is to provide a means of fine tuning QByteArray's memory usage. In general, you will rarely ever need to call this function. If you want to change the size of the byte array, call resize().

the following code mustn't reallocate memory:


QByteArray array;
array.reserve(1024);
array.resize(1024);
assert(array.capacity() == 1024); // ok
array.resize(120);
assert(array.capacity() == 1024); // fail
What is wrong?

Thank you.

SixDegrees
21st August 2010, 10:49
What does array.capacity() return? Print the value to the console.

I suspect, though, that reserve() is meant as an aid for declaring arrays of larger than default initial capacity. resize(), then, still does what it is documented to do - changes the size of the array, shrinking it if required.

If you need a constant block of memory with a variable "end" to it, you'll probably have to manage that yourself.

squidge
21st August 2010, 10:56
I seem to recall that resize (and of course all the functions which inherently call resize, like chop) actually shrink the allocation, therefore reserve is meant for if you are going to be constantly growing the array, not if your going to be shrinking it.

Checking the source, it seems to confirm this:
"Qt 5.0: We need to add the missing capacity bit (like other tool classes have), to maintain the reserved memory on resize."

AnatolyS
21st August 2010, 11:00
array.capacity() returns 108, but it does not matter. The core of this problem that resize reallocates memory unexpectedly. Look at QVector. QVector::reserve has the same documentation but one doesn't reallocate memory in this case:


QVector<int> v;
v.reserve(1024);
v.resize(1024);
assert(v.capacity() == 1024); // ok
v.resize(100);
assert(v.capacity() == 1024); // ok
Any comments?

AnatolyS
21st August 2010, 11:06
I have looked at sources. QVector already has the capacity bit, but QByteArray has not one:

void QVector<T>::reserve(int asize)
{ if (asize > d->alloc) realloc(d->size, asize); if (d->ref == 1) d->capacity = 1; }
template <typename T>
void QVector<T>::resize(int asize)
{ realloc(asize, (asize > d->alloc || (!d->capacity && asize < d->size && asize < (d->alloc >> 1))) ?
QVectorData::grow(sizeOfTypedData(), asize, sizeof(T), QTypeInfo<T>::isStatic)
: d->alloc); }

jasf
8th March 2012, 11:50
You can use simple code:



class QExtByteArray : public QByteArray
{
public:
QExtByteArray() {}
~QExtByteArray() {}

public:
void clear();
};

void QExtByteArray::clear()
{
data_ptr()->size = 0;
}


clear() function set internal QByteArray size variable to zero, but alloc size will stay the same.