C++ 如何管理返回到QML的动态分配QObject的生存期?

C++ 如何管理返回到QML的动态分配QObject的生存期?,c++,qt,garbage-collection,qml,dynamic-allocation,C++,Qt,Garbage Collection,Qml,Dynamic Allocation,我有以下代码: QVariant componentFromCode(QString code) { QQmlComponent * component = new QQmlComponent(engine); engine->setObjectOwnership(component, QQmlEngine::JavaScriptOwnership); connect(component, &QQmlComponent::destroyed, this, &

我有以下代码:

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()
强制垃圾收集,但是
destrocted()
信号从未发出,因此对象从未被删除。据我所知,这应该是在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
或者


我认为物体没有泄漏。试试这个:

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"; }
};
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

似乎当应用程序存在时,它不会处理
destrocted()
信号,因此
echo()
插槽永远不会触发,这可能会误导您相信对象正在未经管理地泄漏。我不确定这是Qt设计的产品还是bug。
Test
对象在
main()
中的堆栈上实例化,因此当由QML管理的对象被销毁时,它肯定仍然是“活动的”,它使用的事件循环也应该是活动的,所以我希望在应用程序退出之前看到
echo()
,但情况似乎并非如此。但这并不是问题的范围,问题的关键在于对象是被管理的,当它们不再被引用并触发垃圾收集时,它们将被收集。

你的意思是你显式地调用
gc()
@sjdowling-我通常是指我的意思;)您不知道吗?QML中的
堆栈
是什么类型的对象?你能把代码或参考添加到文档中吗。Thanks@user3735658什么时候清除堆栈?在堆栈上的引用被销毁之前,或者我缺少堆栈是什么之前,我不希望gc有任何效果?@user3735658:your
堆栈
仍然有对对象的引用吗?请你贴一张好吗?你会增加得到答案的机会。是的,这正是我之前在评论中写的。我不知道为什么OP忽略了我。
function test2() {
    test()
    gc()
}
qml: that object
destructor called
it got destroyed