繁体   English   中英

QML QQmlPropertyList-包含对象生存期和“内存规则”

[英]QML QQmlPropertyList - contained object lifetimes and 'memory rules'

我发现很难确认将插入到QQmlPropertyList中的项目的对象所有权规则设置为C ++中定义的QML组件的一部分时,

Q_CLASSINFO("DefaultProperty", "values")

DTech在QQmlListProperty中询问了类似的问题-可写QList是否违反QML的内存管理规则? ,但他担心删除QML中定义的组件的后果。 通常,我更担心插入列表中的对象的生命周期要求。

现在从我的理解:

  1. 如果从QML创建并插入了子代,则将自动设置其父代,并由QmlEngine管理对象。 (父项应已在附加项上定义)

  2. 如果我从C ++端插入某些内容,则需要自己管理生命周期。 (父项将在附加时为nullptr)

QT文档警告不要“违反QML的内存管理规则”。 http://doc.qt.io/qt-5/qqmllistproperty.html中,但是我找不到任何能以清晰,简洁的方式真正说明这些内容的内容。

目前,我已经围绕矢量实现了包装器,该包装器非常类似于http://doc.qt.io/qt-5/qtqml-referenceexamples-properties-example.html

但是我添加了两个规则:

  1. 追加检查以查看要添加的对象是否具有nullptr父对象,如果有则拥有所有权。
  2. 清除时,如果当前列表的父级拥有任何对象,则对该对象执行'deleteLater'并将其父级设置为nullptr

我假设由于在添加具有nullptr父对象的对象时设置了父对象,因此当父对象超出范围时,QT将删除自动拥有的QObject

还有更多我想念的规则吗?

我的实施代码,以防万一以上需要澄清:

template <typename T>
class QmlListFacade {
 private:
  std::vector<T *> _storage;

  static void append(QQmlListProperty<T> *list, T *newValue) {
    // take ownership of the object if none are currently defined
    auto obj = static_cast<QObject *>(newValue);
    if( obj->parent() == nullptr) {
      obj->setParent(list->object);
    }
    auto internalList = reinterpret_cast<QmlListFacade *>(list->data);
    internalList->_storage.push_back(newValue);
  }

  static int count(QQmlListProperty<T> *list) {
    return reinterpret_cast<QmlListFacade *>(list->data)->_storage.size();
  }

  static T *get(QQmlListProperty<T> *list, int index) {
    return reinterpret_cast<QmlListFacade *>(list->data)->_storage[index];
  }

  static void clear(QQmlListProperty<T> *list) {
    auto internalList = reinterpret_cast<QmlListFacade *>(list->data);
    for( auto item :internalList->_storage){
      // only delete if we are the owners.
      auto obj = static_cast<QObject *>(item);
      if( obj->parent() == list->object){
         obj->setParent(nullptr);
         obj->deleteLater();
      }
    }
    return internalList->_storage.clear();
  }

 public:
  QmlListFacade() = default;


  QQmlListProperty<T> values(QObject *parent) {
    return QQmlListProperty<T>(parent, this, &QmlListFacade::append, &QmlListFacade::count, &QmlListFacade::get,
                               &QmlListFacade::clear);
  }

};

从发现QML脆弱的对象生命周期管理并为此奋斗了近3年的人的角度来看,在那种经验之窗中,我没有遇到任何处理声明性定义的对象树的情况。

问题在于动态创建的对象,这些对象有时会被删除,无论它们是否具有父对象或代码中存在多少对它们的有效引用。 如果要确保不会将其删除,请给他们明确的CPP所有权。

这样可以防止引擎在使用过程中破坏这些物体。 当对象的父对象销毁时,仍会收集对象,就像在C ++ API中那样。

请注意,此警告仅出现在接受QList的构造函数中,而不包含接受控制功能指针的构造函数。 因此,如果您不使用该格式,则至少可以感到满意。 我对两者都进行了大量测试,因此没有遇到任何功能差异。 除了未提供任何含义和含义的上下文之外,该警告可能被放错了位置,措辞不佳甚至完全没有意义。 只是要彻底测试才能发现婴儿期的任何问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM