1

Here is the implementation of QVector's append() from github:

template <typename T>
void QVector<T>::append(const T &t)
{
    if (d->ref != 1 || d->size + 1 > d->alloc) {
        const T copy(t);
        realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T),
                                           QTypeInfo<T>::isStatic));
        if (QTypeInfo<T>::isComplex)
            new (p->array + d->size) T(copy);
        else
            p->array[d->size] = copy;
    } else {
        if (QTypeInfo<T>::isComplex)
            new (p->array + d->size) T(t);
        else
            p->array[d->size] = t;
    }
    ++d->size;
}

Why does it need to make a copy of t if the number of references to the vector != 1 or it needs to resize and why does it make a copy only for these conditions?

A related question has been asked here, but in the code there a copy of t is always made before appending to the underlying array.

Community
  • 1
  • 1
foriequals0
  • 181
  • 1
  • 6
  • The second condition (it needs to resize) is most likely to avoid destroying an objects due to the resize for which a copy is meant to be appended: if `t` is a reference to an element in the vector it would be invalidated before it is added. I don't know about the other conditiion. – Dietmar Kühl May 13 '17 at 22:10
  • 1
    It's an interesting implementation choice. From looking at MSVC implementation of `std::vector::push_back()`, they don't make a temporary copy of the passed value like this. Instead they first allocate new array (without destroying old one), copy-construct the value at the end of the new array and only after that deallocate the old array. Seems to be more efficient. – zett42 May 13 '17 at 22:24
  • @zett42, do you mean MSVC's implementation is more efficient? If so can you elaborate why and how much more efficient it would be? – foriequals0 May 14 '17 at 00:11
  • Just for the record: Qt's QVector is an implicitly shared container and because of that there is the "d->ref != 1" check (copy-on-write). – Lorenz May 14 '17 at 07:59

1 Answers1

4

At a quick glance it is probably because the if part is for when the vector reallocates whereas the else part is for when it doesn't. When it does reallocate the user could have done vector.append(vector[index]) in which case t would become invalid after the reallocation, therefore a copy must be made before reallocating. In the else part without a reallocation t will stay valid and no copy is necessary.

nwp
  • 9,623
  • 5
  • 38
  • 68