Q_GADGET 与用于从 QML 操作 C++ 对象的多态树的访问器对象 [英] Q_GADGET vs an accessor object for manipulating a polymorphic tree of C++ objects from QML

查看:67
本文介绍了Q_GADGET 与用于从 QML 操作 C++ 对象的多态树的访问器对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 C++ 类型的多态树,我需要从 QML 使用它.内存使用和性能在这里很关键,所以我想知道哪种方法更有效:

I have a polymorphic tree of C++ types that I need to work with from QML. Memory usage and performance are key here, so I wonder which approach would be more efficient:

  • Q_GADGET - 毫无疑问,这是一种更简单快捷的方法.我可以直接使用属性(没有通知,因此也没有绑定)和插槽来访问每个对象的成员.它依赖于元数据生成和 qtquick 运行时中的某种对象标识.

  • Q_GADGET - without a doubt the easier and faster way to do it. I can directly use properties (without notifications so no bindings either) and slots to access each object's members. It relies on meta data generation and some kind of object identification in the qtquick runtime.

使用全局访问器对象来访问所有内容、获取或设置对象属性、调用函数等.这绝对是更慢、更冗长的解决方案.

Use an global accessor object for accessing everything, getting or setting object properties, invoking functions and so on. This is definitely the slower and more verbose solution.

我之前曾尝试将 QObject 派生类型注册为 QML 类型,但内存使用情况非常糟糕.我从 QObject 单独获得了巨大的开销——基本 16 字节数据集的开销大约为 140 字节,在 QML 中实例化对象更糟,将开销飙升到大约 2000 字节.考虑到我正在处理的大量对象,这是不可接受的.

I have previously tried with QObject derived types registered as QML types, but memory usage was horrific. I had huge overhead from QObject alone - about 140 bytes overhead for the base 16 byte data set, and instantiating the objects in QML made that even worse, soaring the overhead to around 2000 bytes. Which is unacceptable considering the high object count I am dealing with.

所以现在我要走很长的路,放弃以前的设计,想知道什么是最有效的实现.此外,与 Q_GADGET 相关的元数据是否能在多态场景中很好地工作.

So now I am going the long way, and scrapping the previous design, and wonder what would be the most efficient implementation to take. Also, whether the meta stuff associated with Q_GADGET will work out nicely in a polymorphic scenario.

推荐答案

所以我决定对这两种方法进行测试并进行比较.

So I decided to give both approaches a test run and make a comparison.

幸运的是,由于 Qt 通常的强制性限制,我的努力被缩短了,结果是 Q_GADGET 不适用于指针,在指针上使用它们时,属性和函数都不可用基础.

My efforts were cut short, thankfully in their infancy, by the usual obligatory Qt limitation - turns out Q_GADGET doesn't work with pointers, neither properties nor functions are available when working with them on pointer basis.

成员访问仅支持实例,因此该选项不适用于多态场景.它是手动访问器对象!

Only instances are supported for member access, therefore that option is not applicable in a polymorphic scenario. Manual accessor object it is!

更新:

对此有一个解决方法,但它涉及额外的工作.实现 PIMPL 惯用法,您可以让对象实例实现属性,只需将其作为指向实际实现的指针,从而使所有复制都适用且高效.

There is a workaround for this, but it involves extra work. Implementing the PIMPL idiom you can have the object instance implementing the properties simply being a pointer to the actual implementation, making all the copying around applicable and efficient.

然而,我最终没有使用这种方法,主要是因为它仍然不支持通知,而且第 3 方"通知实现的效率太低了.相反,我为每个对象使用了一个基于 QObject 的代理"或访问器",由 QML 元素引用.代理是按需创建的,并且是引用计数的,因此它仅在需要对象-> qml"桥时才存在,这始终仅适用于所有对象的一个​​非常小的子集.代理与对象紧密耦合以避免查找它的惩罚,而 GUI 本身仍然被抽象掉.

I ended up not using that approach however, mainly due to the fact it still did not support notifications, and the "3rd party" notification implementation turned out to be too inefficient. Instead I went for a QObject based "proxy" or "accessor" for every object, referenced by a QML element. The proxy is created on demand, and is reference counted, so it only exists whenever an "object -> qml" bridge is needed, which is always only for a very small subset of all objects. The proxy is tightly coupled with the object to avoid penalties of looking it up, while the GUI itself is still abstracted away.

与旧的、基于 QML 对象的实现相比,该实现的实际优势令人印象深刻.从在 32 位构建上耗尽内存大约 300k 个对象,它现在能够处理大约 500M,提高了 1666 倍.

The real world advantage of that implementation compared with the old, QML object based is impressive. From running out of memory on a 32bit build around 300k objects, it is now capable of handling around 500M, a 1666x fold improvement.

这篇关于Q_GADGET 与用于从 QML 操作 C++ 对象的多态树的访问器对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆