gpt4 book ai didi

garbage-collection - QML 内存管理

转载 作者:行者123 更新时间:2023-12-05 03:13:57 24 4
gpt4 key购买 nike

我正在尝试测试 QML 以了解它如何与 C++ 一起工作。我有 ClassAClassB - 2 个类似的 C++ 类。这是一个 ClassA。所有方法的名称都是自解释的,所以我不会在这里放置实现。

class ClassB;
class ClassA : public QObject
{
Q_OBJECT
public:
explicit ClassA(QObject *parent = 0);
~ClassA();
Q_PROPERTY(ClassB* classB READ getClassB WRITE setClassB NOTIFY classBChanged)
ClassB* getClassB() const;
void setClassB(ClassB *classB);
signals:
void classBChanged();
private:
ClassB *m_classB;
};

ClassB也是一样,只是把所有的*lassA*都改成*lassB*,所有的*lassB* > 到 *lassA*

然后我用 QML 注册这两个类

qmlRegisterType<ClassA>("testmodule.test",1,0,"ClassA");
qmlRegisterType<ClassB>("testmodule.test",1,0,"ClassB");

QML 代码中,鼠标单击时我创建了两个对象,如下所示:

onClicked: {
var comp = Qt.createComponent("TClassA.qml"); //TClassA.qml is
//a component of type
//ClassA
var ca = comp.createObject();
comp = Qt.createComponent("TClassB.qml");
var cb = comp.createObject();
ca.classB = cb;
cb.classA = ca;
parent.blockFromGC = ca;
}

然后我用 gc() 调用垃圾收集器。我预计 caparent.blockFromGC 阻止删除, cbca 引用阻止删除.但是垃圾收集器销毁了 cb 之后 parent.blockFromGC.classB === null

所以我有第二个 MouseArea 代码:

onClicked: {
console.log(mouse.button)
// if (mouse.button == Qt.RightButton) {
// console.log(parent.vasya.classB)
// }
gc();
console.log(parent.blockFromGC.classB) //I use cb here
}

所以当我点击 MouseArea 时,我进入了控制台:

qml: 1 //Left button
qml: null //value of parent.blockFromGC.classB
classB destroyed: TQMLClassB(0x34960d0) //I have qDebug() in destructor

所以我的对象 cb 被销毁了。

所以我有这个问题:

1) 有没有办法将 C++ 类型注册为基本类型,这样我就可以写 var ca = new ClassA() 而不是创建一个 *.qml 文件,创建一个组件,最后创建一个对象?

2) 为什么垃圾收集器破坏了我的 cb 对象,我该怎么办防止这个对象被删除?

此外!如果我取消注释那些注释行

//    if (mouse.button == Qt.RightButton) {
// console.log(parent.vasya.classB)
// }

无论我按下哪个按钮,对象都不会再被销毁。

qml: 1 //left button
qml: TQMLClassB(0x3df8e90) //object is alive
.....
qml: 2 //right button
qml: TQMLClassB(0x3df8e90) //before gc() - alive
qml: TQMLClassB(0x3df8e90) //after gc() - alive

3) 我在哪里可以详细了解 QML 内存管理?我发现这种行为真的很奇怪..

补充 1:我对这种情况进行了更多尝试,但结果无法预测。我从 5.3 更新到 Qt 5.4,这种对象删除行为已经消失。问题在于该行为是如此不可预测,以至于我无法在 Qt 5.4 中重现该行为并不意味着问题已解决。我会尝试查看错误报告和错误修复。如果我找到了什么,我会把它贴在这里。如果没有,我将尝试在 Qt 5.4 中重现这种情况并发布报告。

最佳答案

  1. 与任何 QML 类型一样,您可以在另一个组件中静态定义一个组件:

    Component {
    id: classAComponent
    ClassA { }
    }
    onClicked {
    var ca = classAComponent.createObject()
    }
  2. 这里有一个微妙之处:将 QML 对象分配给 QML 属性 将增加其 JavaScript 引用计数。但是,存储在 C++ 对象的 Q_PROPERTY 中的实例不会被垃圾收集器标记。

    QML 具有双重所有权系统。首先,它定义了用于显示和所有权的 QObject/QQuickItem 层次结构。连接到这个主干的是一个垃圾收集系统,其中任何 QML 对象都可以通过 property var 拥有一棵 JavaScript 对象树。

    因此,为了让您的 ClassB 对象保持事件状态,您要么必须将其保存在 QML 属性中,要么在调用 component.createObject() 时为其提供一个父对象(这是一个硬所有权;它将当父级被销毁时,无论任何 JS 引用它都会被销毁)

    带有 QML 属性的示例:

    Component {
    id: classAComponent
    ClassA {
    property Item refClassB
    }
    }
    onClicked {
    var ca = classAComponent.createObject()
    ca.refClassB = classBComponent.createObject()
    }

    理想情况下,您应该尽可能避免动态创建对象,并像普通 QML 组件一样静态使用 C++ 对象,并让声明式结构自动维护 QObject 主干,如下所示:

    ClassA {
    classB: ClassB { }
    }
  3. 遗憾的是,据我所知,QML 比 C++ 更多的是 Dynamic QML Object Creation from JavaScript .

关于garbage-collection - QML 内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27981784/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com