На основе документации Qt всякий раз, когда тип указателя QObject передается из кода C ++ в QML, с помощью метода Q_INVOKABLE , существует набор правилкоторые определяют, кто отвечает за время жизни этого указателя.Если QObject не имеет родителей, то неявно, что механизм QML отвечает за принятие владения указателем.
В моем сценарии я хочу, чтобы мой интерфейс внешнего интерфейса представлял модель списка, которая генерируется / предоставляетсяс помощью внутреннего кода C ++.Мое предположение состоит в том, что указатель будет оставаться в живых до тех пор, пока на него ссылается код QML.Приведенный ниже код показывает сокращенный тестовый пример:
Main.cpp
#include <QAbstractItemModel>
#include <QDebug>
#include <QGuiApplication>
#include <QObject>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QStringListModel>
class MyStringListModel : public QStringListModel
{
Q_OBJECT
public:
explicit MyStringListModel(const QStringList &strings, QObject* parent=nullptr) : QStringListModel(strings, parent)
{
qDebug() << "Creation";
}
virtual ~MyStringListModel() override
{
qDebug() << "Destruction";
}
};
class Backend : public QObject
{
Q_OBJECT
public:
Backend(QObject* parent=nullptr) : QObject(parent)
{
}
Q_INVOKABLE QAbstractItemModel* createModel() const
{
static const QStringList months = {
tr("January"),
tr("February"),
tr("March"),
tr("April"),
tr("May"),
tr("June"),
tr("July"),
tr("August"),
tr("September"),
tr("October"),
tr("November"),
tr("December"),
};
return new MyStringListModel(months);
}
};
int main(int argc, char* argv[])
{
QGuiApplication application(argc, argv);
qmlRegisterType<QAbstractItemModel>();
Backend backend;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("backend", &backend);
engine.load("qrc:///ui/main.qml");
return application.exec();
}
#include "main.moc"
Main.qml
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.1
ApplicationWindow {
id: window
width: 200
height: 250
visible: true
ColumnLayout {
anchors.fill: parent
anchors.margins: 10
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
model: backend.createModel()
delegate: Text {
anchors.horizontalCenter: parent.horizontalCenter
text: model.display
}
}
Button {
Layout.alignment: Qt.AlignCenter
text: qsTr("Garbage Collect")
onClicked: gc()
}
}
}
Это скриншот программы:
В тот момент, когда пользователь нажимает на кнопку, сборщик мусора запускается и уничтожает модель ptr (уничтожение становится очевидным из "«Создание» и «Уничтожение» (вывод на стандартный вывод).
Мне интересно узнать, почему указатель был уничтожен?Я заметил, что он не установил ListView в качестве своего родителя, что достаточно справедливо, я подумал, что механизм QML использовал бы некоторую форму ссылочного указателя, чтобы попытаться отследить, кто все еще держитссылка на это.Есть ли документ, который дает более полное представление о том, как реализована сборка / владение мусором.
Аналогично, есть ли лучший способ структурирования этого кода, при этом все еще удовлетворяя требованиям прохождения без родительского QObject вернуться к QML.