5

这个简单片段的执行:

{
  QModelIndexList sel = ui->tableView->selectionModel()->selectedRows(0);
  sel.at(0).isValid(); // To prevent removing the previous line by optimization
}

takes more than 30 seconds when the number of selected rows is about one million. 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,或者我可以以某种方式加速销毁?

4

1 回答 1

5

不幸的是, AQList将在每个模型索引上执行内存分配和删除。出于某种原因,在您的平台上,释放速度非常慢。

QList作为一种解决方法,您可以在工作线程中运行解除分配,利用隐式共享类这一事实。

这假设QModelIndex在非 gui 线程中删除 a 是安全的。您必须审核您的代码和相关的 Qt 代码来确定这一点。

C++11

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.

C++14

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.

有关可移动类型的 lambda 捕获技术,请参阅此问题

C++98

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));
}

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

于 2016-04-01T13:03:16.840 回答