2017-05-13 29 views
1

这里是QVector的append()从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; 
} 

为什么它需要做的t一个副本,如果该矢量引用数= 1或它需要调整?为什么!它仅为这些条件制作副本?

已经询问here的相关问题,但是在代码中,总是在附加到底层数组之前创建副本t

+0

第二个条件(它需要调整大小)最有可能避免销毁由于要附加副本的调整大小而产生的对象:如果“t”是对向量中元素的引用,它将是在添加之前无效。我不知道另一个条件。 –

+1

这是一个有趣的实现选择。通过查看'std :: vector :: push_back()'的MSVC实现,它们不会像这样创建传递值的临时副本。相反,他们首先分配新数组(不破坏旧数组),然后在新数组末尾复制构造值,然后再释放旧数组。似乎更有效率。 – zett42

+0

@ zett42,你是说MSVC的实现更有效率? 如果能,那么你可以详细说明为什么会更有效率? – foriequals0

回答

3

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