QModelIndexList的析构函数太慢了

时间:2016-04-01 07:43:28

标签: qt qabstractitemmodel qmodelindex

执行这个简单的片段:

{
  QModelIndexList sel = ui->tableView->selectionModel()->selectedRows(0);
  sel.at(0).isValid(); // To prevent removing the previous line by optimization
}
当所选行数约为一百万时,

需要30秒以上。 QModelIndex列表的构造几乎是立即的,但破坏需要永远。 花在这个函数上的时间是:

template <typename T>
Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *from, Node *to)
{
    if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic)
        while(from != to) --to, delete reinterpret_cast<T*>(to->v);
    else if (QTypeInfo<T>::isComplex)
        while (from != to) --to, reinterpret_cast<T*>(to)->~T();
}

有人有解决方案吗?有没有办法在不创建QModelIndexList的情况下获取所选行的索引,还是可以以某种方式加速破坏?

1 个答案:

答案 0 :(得分:5)

遗憾的是,QList将对每个模型索引执行内存分配和删除。出于某种原因,在您的平台上,重新分配非常缓慢。

作为一种解决方法,您可以在工作线程中运行释放,并利用QModelIndex是隐式共享类的事实。

这假设在非gui线程中删除auto sel{ui->tableView->selectionModel()->selectedRows(0)}; // Use sel. sel.at(0).isValid(); // Deallocate in a separate thread. QtConcurrent::run(std::bind([] (QModelIndexList& p) {}, std::move(sel))); // At this point, sel has been moved from and its destruction is trivial. 是安全的。您必须审核您的代码和相关的Qt代码以确定这一点。

C ++ 11

auto sel{ui->tableView->selectionModel()->selectedRows(0)};
// Use sel.
sel.at(0).isValid();
// Deallocate in a separate thread.
QtConcurrent::run([sel{std::move(sel)}] {});
// At this point, sel has been moved from and its destruction is trivial.

C ++ 14

template <typename T> class CopyMoves {
   mutable T data;
public:
   CopyMoves(T & old) { std::swap(data, old); }
   CopyMoves(const CopyMoves & old) { std::swap(data, old.data); }
   void operator()() {}
};

int main() {
   QModelIndexList sel;
   QtConcurrent::run(CopyMoves<QModelIndexList>(sel));
}

有关可移动类型的lambda捕获技术,请参阅this question

C ++ 98

CopyMoves

data类实现了一个在复制构造时移动其std::auto_ptr成员的类。这是auto_ptr使用的可怕黑客(不要使用CopyMoves::data!)。非空CopyMoves成员将在工作线程中被破坏。另外两个data实例,保持空{{1}},将在主线程中被破坏。