PDA

View Full Version : QVector creates double copies on replace, append, ...



Waldemar
30th December 2014, 21:09
Hi there

Today I've noticed that all my appends to QVector create double copies of the data. So after inspection of the code I
found that not just append has the same issue, but replace and others too:

Source code of replace:

template <typename T>
inline void QVector<T>::replace(int i, const T &t)
{
Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::replace", "index out of range");
const T copy(t);
data()[i] = copy;
}


Now can somebody please explain me why a local copy is made?

From my point of view:
1. we don't need a local copy in the first place
2. but if we had it, why is it defined as a 'const', so that even a move operation can't be called on the data??

Now I have to assume that author wanted to do something with this (maybe some compiler issues??), but I can't find the explanation.
Any insights?

Best regards
Waldemar

wysota
30th December 2014, 21:45
The vector, by definition, holds copies. Whether these are shallow or deep copies, it depends on the data held but they are still copies. The reference operator does not create a copy therefore a copy had to be made explicitly before the assignment operator was used.

Waldemar
30th December 2014, 22:01
I've done some more inspection and there is no move semantics used on the QVector items.
I've updated QVector on my local code, but don't understand why this isn't done by default already?

Added after 5 minutes:

To wysota:
This can't be really the reason. The thing is that as soon as we define an argument with a 'const reference' the compiler will automatically call copy constructor/operator even if we use it as:


template <typename T>
inline void QVector<T>::replace(int i, const T &t)
{
Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::replace", "index out of range");
data()[i] = t;
}

Of course I can be wrong... do you have some example in which circumstances a 'const reference' wouldn't call copy constructor/operator?

wysota
30th December 2014, 22:45
Of course I can be wrong... do you have some example in which circumstances a 'const reference' wouldn't call copy constructor/operator?
I never claimed anything like this. Indeed the data is copied twice during append, I don't know why, this is different to std::vector.

You could try looking here for answers: http://doc.qt.digia.com/qq/qq19-containers.html. The behavior changes if you use Q_DECLARE_TYPEINFO on your class and make it a primitive type.

Maybe it has something to do with reference counting (to ensure the count doesn't drop between a certain value during assignment)?