20200514-02 C++ 指針所有權 QML 等釋放控件重新讀取 C++ 指針出現異常或發現指針被釋放等問題說明

一、前言

  寫 QML 這麼久,卻因爲英文所限沒有認真解讀,QML 與 C++ 交互最重要的一條就是傳遞到 QML 的 C++ 對象的所有權,在實際項目開發中會會發現,tableview 或者其他控件被釋放之後重新讀取原先的 C++ 對象就會發生內存異常,從而導致程序奔潰。
  調試之後,會發現是由於 C++ 指針被釋放了,當 QML 控件被釋放的時候同時釋放了 C++ 對象

二、數據權限 Data Ownership

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 never delete a QObject instance which has a parent.

大致翻譯如下:
當數據從 C++ 傳遞到 QML 中時,C++ 通常會保留這個數據的所有權;但是,當 QML 通過聲明的方法從 C++ 獲取一個 QObject 對象的指針時,QML 將會獲取這個 QObject 對象的所有權,除非顯式調用 QQmlEngine::setObjectOwnership() 方法並指定爲 QQmlEngine::CppOwnership
通常來說 QML 不會主動更改正常 QObject 對象父類,也就不會刪除一個擁有父類的 QObject 實例(父類不是 QML)

根據最後一句話,可以得出結論,只要在 new 一個 QObject 對象的時候聲明父類 比如 new QObject(this) 就可以避免 QML 釋放自身控件的時候同時把 C++ 對象釋放

三、實際使用感言

  在實際嵌入式設備開發中,特別是 TableView 如果涉及到控件比較複雜,控件加載會消耗很多 CPU 資源從而導致使用過程中出現卡頓的情況,通過將控件與 C++ 對象綁定,就可以避免刷新界面從而只要刷新底層數據指針通過 QML 與 C++ 交互方式就可以用極快的方式完成數據的顯示和處理
  當時 QML 與 底層數據是多線程情況,但 QML 無法與非同線程對象建立信號關係,所以可以考慮直接在 QML 線程處動態生成 delegate 對象,以保證交互所需

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章