了解 QVector append() - 为啥它有条件地复制?

Posted

技术标签:

【中文标题】了解 QVector append() - 为啥它有条件地复制?【英文标题】:Understanding QVector append() - Why does it copy conditionally?了解 QVector append() - 为什么它有条件地复制? 【发布时间】:2017-05-13 21:40:35 【问题描述】:

这是来自github的QVector的append()的实现:

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;

如果对向量的引用数 != 1 或它需要调整大小,为什么它需要复制 t,为什么它只在这些条件下复制?

here 提出了一个相关问题,但在代码中,t 的副本总是在附加到基础数组之前创建。

【问题讨论】:

第二个条件(它需要调整大小)最有可能避免由于要附加副本的调整大小而破坏对象:如果t 是对一个元素的引用在添加之前将使其无效的向量。我不知道其他条件。 这是一个有趣的实现选择。通过查看std::vector::push_back() 的 MSVC 实现,他们不会像这样对传递的值进行临时副本。相反,他们首先分配新数组(不破坏旧数组),复制构造新数组末尾的值,然后才释放旧数组。似乎效率更高。 @zett42,你的意思是MSVC的实现效率更高吗?如果是这样,您能否详细说明为什么以及效率会提高多少? 仅作记录:Qt 的 QVector 是一个隐式共享容器,因此存在“d->ref != 1”检查(写时复制)。 【参考方案1】:

乍一看,这可能是因为if 部分用于向量重新分配时,而else 部分用于不重新分配时。当它重新分配时,用户可能已经完成了vector.append(vector[index]),在这种情况下t 在重新分配后将变得无效,因此必须在重新分配之前进行复制。在else 部分没有重新分配t 将保持有效并且不需要复制。

【讨论】:

以上是关于了解 QVector append() - 为啥它有条件地复制?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 QVector 的迭代器使用前缀增加而后缀在内部减少?

qvector安插入顺序保存

如何实例化并附加到指向我的对象的指针的 QVector

QCustomPlot 使用——绘制折线图

Qt开发经验小技巧186-190

QVector内存泄漏?