将Qt对象(QgraphicsItem)转换为C++类对象的最佳方法是什么

what is the best way to convert a Qt object(QgraphicsItem) into C++ class object

本文关键字:对象 最佳 方法 是什么 C++ 转换 Qt QgraphicsItem      更新时间:2023-10-16

我正试图在类似的循环中将Qt对象转换为C++类对象

std::vector<PBWMPlugDeviceGraphicsItem*> deviceItms;
for(int i=0; i<fScene->items().size(); i++)
    deviceItms.push_back(dynamic_cast<PBWMPlugDeviceGraphicsItem*>(fScene->items().at(i)));

其中PBWMPlugDeviceGraphicsItem是C++类。似乎,当项目总数大于某个阈值(例如fScene->items().size() >900)时,转换这些对象需要相当长的时间,因此我可以看到QGraphicsScene上的操作非常缓慢。我读到dynamic_cast存在严重的性能问题。

有没有其他好的/快速的方法可以达到同样的结果?

谢谢!

使用此:

for (auto p: fScene->items())
    deviceItms.push_back(dynamic_cast<PBWMPlugDeviceGraphicsItem*>(p));

两个重要区别:

  • 它只调用fScene->items()一次。除非该函数通过(const)引用返回,否则为每次迭代检索和丢弃容器是无用的开销,特别是如果内容不应该在迭代之间更改的话
  • 它不使用索引并在at()中验证该索引,而是使用C++11用于带有自动类型化变量的循环。只有当您怀疑索引是否有效(例如,当它是从用户输入的)时,at()才有用,但如果您不能编程一个简单的循环,那么您确实有更重要的问题

我没有进行使用vector::reserve()预分配内存的第三次优化。如果你真的只有几个对象(是的,900是很少的),那么它可能很难被注意到。尽管如此,还是要对此进行一些研究,因为这是一个你应该了解的工具。

for(int i=0; i<fScene->items().size(); i++)
  deviceItms.push_back(dynamic_cast<PBWMPlugDeviceGraphicsItem*>(fScene->items().at(i)));

根据评论回复,fScene->items()似乎返回了类似QList<QGraphicsItem *>的内容。

编写代码时,会在每次循环迭代时创建并丢弃此QList的实例。因此,作为第一次优化,我会尝试在循环外部获取列表一次,然后在循环内处理同一实例,避免在每次循环迭代时浪费列表的创建/销毁。

如果你可以使用C++11,我同意@Ulrich关于使用基于范围的for循环的建议:这将使更简单更快


编辑

在这里的一条评论中,你写道,你不能使用C++11,所以你不能享受基于范围的循环
那么,一个替代方案可能是:

// Get the collection of items once, outside the loop
QList<QGraphicsItem *> items = fScene->items();
// For each graphics item in the collection...
for (int i = 0; i < items.size(); i++) {
    deviceItems.push_back(dynamic_cast<PBWMPlugDeviceGraphicsItem*>(items.at(i)));
}

问题是调用QList::at,它返回对列表项的引用,导致QList在写分离时进行复制。

最小的解决方案是调用QList::value来获取指针,而不是at

另一种解决方案是获取列表一次,如其他答案所述。即使使用at,这种分离也只会发生一次。

您还可以通过强制转换或临时变量强制使用at的const版本。

谢谢大家!你的建议很有用。我以以下方式实现(因为我不能使用C++11)

        QList<QGraphicsItem*> temp= fScene->items();
    for(int i=0; i<temp.size(); i++)
        deviceItms.push_back(dynamic_cast<PBWMPlugDeviceGraphicsItem*>(temp[i]));

它运行得非常好。

非常感谢你提供的有用提示!我真的学到了一些新东西。