执行这个简单的片段:
{
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
的情况下获取所选行的索引,还是可以以某种方式加速破坏?
答案 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代码以确定这一点。
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.
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。
CopyMoves
data
类实现了一个在复制构造时移动其std::auto_ptr
成员的类。这是auto_ptr
使用的可怕黑客(不要使用CopyMoves::data
!)。非空CopyMoves
成员将在工作线程中被破坏。另外两个data
实例,保持空{{1}},将在主线程中被破坏。