Bet*_*ker 2 qt pointers qml qtquick2
假设我有一个 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;
};
Run Code Online (Sandbox Code Playgroud)
大多数情况下这有效,但有时会导致崩溃。调用堆栈相当长,但如下所示:
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.
Run Code Online (Sandbox Code Playgroud)
如果我设置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;
};
Run Code Online (Sandbox Code Playgroud)
崩溃消失了。
这是 的已知限制吗Q_PROPERTY?如果您返回指向 a 的指针QObject,则该对象被假定为指针(而不是成员)并且deleteLater()可能会调用类似的东西?
这种崩溃很可能是因为 QML 获取了函数c返回的对象的所有权,并且想要在稍后的某个时刻删除它。在您的第一个示例中,由于x不是从免费存储中分配的,因此尝试删除它会崩溃。在第二个示例中,QML 引擎仍尝试删除它,但这样做没有问题。
要问的问题是为什么 QML 引擎要取得该对象的所有权?文档中指出QML 和 C++ 之间的数据类型转换 | 数据所有权:
当数据从 C++ 传输到 QML 时,数据的所有权始终属于 C++。此规则的例外情况是,当从显式 C++ 方法调用返回 QObject 时:在这种情况下,QML 引擎将假定该对象的所有权,除非已通过调用 QQmlEngine: 将该对象的所有权显式设置为保留在 C++ 中: setObjectOwnership() 并指定了 QQmlEngine::CppOwnership。
此外,QML 引擎尊重 Qt C++ 对象的正常 QObject 父所有权语义,并且永远不会获取已经拥有父对象的 QObject 实例的所有权。
因此,为了解决您的问题,您可以影响对象QObject的父级x,或者明确声明它具有QmlEngine::CppOwnership.
| 归档时间: |
|
| 查看次数: |
1112 次 |
| 最近记录: |