无法在 std::shared_ptr 中保留 QQmlContext

Unable to hold QQmlContext in std::shared_ptr

我在使用 Qt 5.15/C++ 时注意到一些非常奇怪的行为。

当我想为我的根上下文设置上下文 属性 时,我正在开发一个小型应用程序。

我的应用程序是一个 QtQuick 应用程序,它使用 QQmlApplicationEngine 而不是 QQuickView(无论出于何种原因,这是创建 Qt Quick 应用程序时的默认设置):

QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));

// ...

QStringList entryList { "String1", "String2", "String3" };

然后,在将字符串列表分配为我的根上下文的上下文 属性 时,我想使用 STL 共享指针而不是原始指针:

std::shared_ptr<QQmlContext> context = std::make_shared<QQmlContext>(engine.rootContext());

if (!context) {
    qDebug() << "Failed to get root context. exiting.";
    exit(-1);
}

context->setContextProperty("entryList", QVariant::fromValue(entryList));

我的条目列表在 QML 中将为空。

然而,当我使用原始指针时:

QQmlContext* context = engine.rootContext();

// ...

一切正常,entryList var 填充在 QML 中。

这背后有我还不明白的逻辑行为吗?

顺便说一句,当使用 QSharedPointers 而不是 shared_ptr 时,列表将被填充,但是我在退出时遇到调试器异常:

Exception at 0x7ff8022f2933, code: 0xc0000005: read access violation at: 0xffffffffffffffff, flags=0x0 (first chance)

Qt 明确指出了开发人员何时必须管理对象的内存,如果没有指出则必须假定 Qt 会在必要时将其删除。

在这种特殊情况下,QQmlContext 是由 QQmlApplicationEngine 创建的,因此 class 负责管理其内存。例如,QNetworkAccessManager 是一种不同的情况,它在文档中指出开发人员必须处理创建的 QNetworkReply(docs):

的内存

Note: After the request has finished, it is the responsibility of the user to delete the QNetworkReply object at an appropriate time. Do not directly delete it inside the slot connected to finished(). You can use the deleteLater() function.

Qt 负责的内存管理可以通过 QObject 层次结构或使用它自己的指针(QPointer、QSharedPointer 等)来完成,但这与开发人员无关,因为它是私有 Qt 的一部分 API.