了解 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() - 为啥它有条件地复制?的主要内容,如果未能解决你的问题,请参考以下文章