Qt 属性是否假定对象是指针而不是成员?

Do Qt properties assume objects are pointers and not members?

假设我有一个 C++ 对象,其中包含一个我向 QML 公开的成员对象:

class X : public QObject
{
   Q_OBJECT
};
class Y : public QObject
{
   Q_OBJECT
   Q_PROPERTY(X* x READ getX CONSTANT)
public:
   X* getX(void) { return &x; }
   X x;
};

大多数情况下这是可行的,但有时会导致崩溃。调用堆栈很长但是是这样的:

QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData> >::data
qGetPtrHelper<QScopedPointer<QObjectData>>
QObject::d_func
QObjectPrivate::get
QQmlNotifierEndpoint::disconnect
QQmlNotifierEndpoint::~QQmlNotifierEndpoint
QQmlJavaScriptExpressionGuard::~QQmlJavaScriptExpressionGuard
QRecyclePool<QQmlJavaScriptExpressionGuard, 1024>::Delete
QQmlJavaScriptExpressionGuard::Delete
QQmlJavaScriptExpression::GuardCapture::captureProperty
QQmlEnginePrivate::captureProperty
QV4::QObjectWrapper::getProperty
etc.

如果我将 X 设置为指针:

class Y : public QObject
{
   Q_OBJECT
   Q_PROPERTY(X* x READ getX CONSTANT)
public:
   Y()
   { x = new X; }
   X* getX(void) { return x; }
   X* x;
};

崩溃消失了。

这是 Q_PROPERTY 的已知限制吗,如果您 return 指向 QObject 的指针,则假定该对象是指针(不是成员)和其他东西像 deleteLater() 可能被称为?

发生此崩溃的最有可能是因为 QML 取得了对象 c 您的函数 returns 的所有权,并希望稍后将其删除。 在您的第一个示例中,由于 x 不是从免费商店分配的,因此尝试删除它会崩溃。 在第二个示例中,QML 引擎仍然尝试删除它,但没有问题。

要问的问题是,为什么 QML 引擎会取得对象的所有权? Data Type Conversion Between QML and C++ | Data Ownership 中的文档说明:

When data is transferred from C++ to QML, the ownership of the data always remains with C++. The exception to this rule is when a QObject is returned from an explicit C++ method call: in this case, the QML engine assumes ownership of the object, unless the ownership of the object has explicitly been set to remain with C++ by invoking QQmlEngine::setObjectOwnership() with QQmlEngine::CppOwnership specified.

Additionally, the QML engine respects the normal QObject parent ownership semantics of Qt C++ objects, and will not ever take ownership of a QObject instance which already has a parent.

因此,为了解决您的问题,您可以影响 x 对象的 QObject 父对象,或者明确声明它具有 QmlEngine::CppOwnership.