我有这段代码:
QVariant componentFromCode(QString code) {
QQmlComponent * component = new QQmlComponent(engine);
engine->setObjectOwnership(component, QQmlEngine::JavaScriptOwnership);
connect(component, &QQmlComponent::destroyed, this, &Factory::echo);
component->setData(code.toUtf8(), QUrl());
return QVariant::fromValue(component);
}
但永远不会调用Factory::echo()
,这意味着每次调用函数时对象都会泄露。
这就是我在QML方面所拥有的:
onClicked: {
var code =
'import QtQuick 2.3
Rectangle {
width: 50
height: 50
color: "blue"
}
'
stack.push(Factory.componentFromCode(code))
gc()
}
我明确设置了对象所有权,并显式调用gc()
来强制进行垃圾回收,但destroyed()
信号永远不会被发出,因此对象永远不会被删除。根据我的阅读,这应该在QML中自动发生。
请注意,它适用于:
var comp = Factory.componentFromCode(code)
stack.push(comp)
comp.destroy()
但这只是不方便,我想让对象自动销毁,因为它超出了范围,或者只要它被QML代码引用就会保持活着,并且当它是不再需要,在许多情况下手动操作可能很难/荒谬。
编辑:堆栈示例碰巧是我的实际代码,但我想这不是一个好例子,看看堆栈是如何承担对组件的所有权的。即使在如此简单的情况下,我也无法获得任何终身管理:
function JSfoo() {
var obj = CXTProp.getCppQObjectStar()
console.log(obj.objectName)
} // QObject is not collected here
...或
QtObject {
property QtObject: CXTProp.getCppQObjectStar()
} // QObject is not collected after the object is destroyed
答案 0 :(得分:4)
我不认为物体在泄漏。试试这个:
class TestObj : public QObject {
Q_OBJECT
public:
~TestObj() { qDebug() << "destructor called"; }
};
class Test : public QObject {
Q_OBJECT
public:
explicit Test(QObject *parent = 0) : QObject(parent) {}
public slots:
QVariant getObject() {
QObject * obj = new TestObj;
obj->setObjectName("that object");
connect (obj, &TestObj::destroyed, this, &Test::echo);
return QVariant::fromValue(obj);
}
void echo() { qDebug() << "it got destroyed"; }
};
和QML:
function test() {
var test = Test.getObject()
console.log(test.objectName)
}
在收集test()
对象后,当您关闭应用程序时,永远不会触发echo()
插槽,但析构函数中的调试语句确实显示在控制台中:
qml: that object
destructor called
如果你在函数范围内调用gc()
它不起作用,可能是因为该对象仍在其中引用:
function test() {
var test = Test.getObject()
console.log(test.objectName)
gc() // doesn't do anything
}
但是,如果你这样做:
function test2() {
test()
gc()
}
它有效,因为在对象的引用超出范围之后触发了垃圾收集:
qml: that object
destructor called
it got destroyed
似乎当应用程序存在时,它不会处理destroyed()
信号,因此永远不会触发echo()
插槽,这可能是误导您相信对象泄漏不受管理的原因。我不确定这是Qt设计的产品还是一个bug。 Test
对象在main()
的堆栈中实例化,所以它应该仍然是#34; alive&#34;当由QML管理的对象被销毁时,应该是它使用的事件循环,所以我希望在应用程序退出之前看到echo()
,但似乎情况并非如此。但这不是问题的范围,问题的关键是对象被管理,并且当它们不再被引用并且触发垃圾收集时将被收集。