【问题标题】:Destructor of QModelIndexList is too slowQModelIndexList 的析构函数太慢
【发布时间】:2016-07-20 22:19:16
【问题描述】:

这个简单sn-p的执行:

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

当所选行数约为100万时需要超过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 的情况下获取选定行的索引,或者我可以以某种方式加速销毁?

【问题讨论】:

  • 您在使用 Visual Studio 吗?我在大地图上遇到了类似的问题,我已经解决了禁用堆调试(将 _NO_DEBUG_HEAP=1 设置为环境变量)(也在发布模式下,但如果应用程序在 Visual Studio 之外运行则不需要)
  • 谢谢。我正在使用 MinGW。

标签: qt qabstractitemmodel qmodelindex


【解决方案1】:

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

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

假设在非 gui 线程中删除 QModelIndex 是安全的。您必须审核您的代码和相关的 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.

请参阅this question 了解可移动字体的 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 使用的可怕的hack(不要使用auto_ptr!)。非空的CopyMoves::data 成员将在工作线程中被破坏。 CopyMoves 的另外两个实例,持有空的data,将在主线程中被销毁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-13
    • 1970-01-01
    • 2022-01-11
    • 2011-08-18
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多