将对象从c ++发送到qml.那些免费记忆?

lir*_*k90 2 c++ qt memory-leaks qml

有一个继承自QAbstractListModel的模型,我在qml中使用它.此模型的一个属性是参数,它们特定于此模型的元素类型.这是此类参数的一个元素TemperatureParam,DifrentParamType另一个,第三个仍然是...我怎样才能将对象传递给qml并确保在使用后释放内存?下面的代码现在可以正常工作,但在我看来它并不安全.

Param类是如此微不足道:

class QuickTemperatureParam : public QObject
{
    Q_OBJECT
    Q_PROPERTY(float param1 READ param1 WRITE setParam1)
//...
};
Run Code Online (Sandbox Code Playgroud)

模型类(这是我要问的):

class SectionsModel : public QAbstractListModel
{
//...
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override
{
//...
    int type = getType( idx );
    if (type == 1)
    {
        auto p = new QuickTemperatureParam( idx );
        p->deleteLater(); // This is all right or no?
        return qVariantFromValue(p);
    }
    else if (type == 2)
    //...
}
};
Run Code Online (Sandbox Code Playgroud)

QML是这样的:

ListView {
    model: sectionsModel

    delegate: Rectangle {
        color: model.statusColor

        ItemDelegate {
            text: model.title
            highlighted: ListView.isCurrentItem

            onPressed:
                switch ( model.type )
                {
                case SectionType.Temperature:
                    temperatureParam.openItem(model)
                    break;
                case SectionType.Lighting:
                    lightingParam.open(model)
                    break;
                }
        }
    }
}

Popup {
    id: temperatureParam

    function openItem(model)
    {
        var p = model.param

        params.itemAt(0).range.from = params.itemAt(1).range.from = p.min
        params.itemAt(0).range.to = params.itemAt(1).range.to = p.max

        params.itemAt(0).range.setValues( p.dayMin, p.dayMax )
        params.itemAt(1).range.setValues( p.nightMin, p.nightMax )

        open()
    }
}
Run Code Online (Sandbox Code Playgroud)

Tar*_*rod 5

根据文件:

当数据从C++传输到QML时,数据的所有权始终保留在C++中.此规则的例外是从显式C++方法调用返回QObject时:在这种情况下,QML引擎假定对象的所有权,除非通过调用QQmlEngine ::显式设置对象的所有权保留在C++中指定了QQmlEngine :: CppOwnership的setObjectOwnership().

通常,应用程序不需要显式设置对象的所有权.正如您在此处所读到的,默认情况下,由QML创建的对象具有JavaScriptOwnership.

从C++方法调用返回的对象也将设置为,JavaScriptOwnership但这仅适用于Q_INVOKABLE方法或插槽的显式调用.

由于该方法data不是显式C++方法调用,因此应考虑将对象所有权设置为QQmlEngine::JavaScriptOwnership调用setObjectOwnership()

所以,一般来说:

  • QQmlEngine::CppOwnership如果您希望QML销毁对象,请不要使用.适当时将删除关联的数据(即在垃圾收集器发现没有更多对该值的实时引用之后)
  • 一个QSharedPointer可能是行不通的.你在这里有更多的信息.

  • 那么,为了安全起见,在将 `new` 对象移交给 QML 时始终设置 `QQmlEngine::JavaScriptOwnership` 是否合理,即使上述暗示 QML 将获得所有权?在那种情况下,我会考虑这样使传输更清晰:`template <typename T> T* TransferObjectOwnershipToJavaScript(std::unique_ptr<T> ptr) { T* result = ptr.get(); QQmlEngine::setObjectOwnership(ptr.release(), QQmlEngine::JavaScriptOwnership); 返回结果;}`。 (2认同)