[英]How should I store pointers in Qt?
我的寵物項目已經到了我應該開始跟蹤指針生命周期的程度,我正在嘗試為它開發一些系統。 遺憾的是,由於Qt API本身在每個場合都使用裸指針,所以在各地都使用智能指針的流行建議並不適用。 所以,我想出的是:
對於Qt所擁有的一切,
QPointer
,在轉換為naked之前進行isNull()
檢查。 對於我所擁有的一切,請按照建議使用智能指針。 我將在這里使用std::
版本。
困擾我的案例。 對於切換所有權的對象(例如從布局添加/刪除的小部件)
delete
它們。 建議,意見,建議? 我自己並不喜歡這個計划。
首先,盡可能按價值保存。 查看new
, make_unique
和make_shared
每個用法 - 您必須證明每個動態對象的創建是正確的。 如果子對象具有與父對象相同的生命周期,則按值保持是一個明智的選擇。 例如:
class MyWidget : public QWidget {
Q_OBJECT
QGridLayout m_topLayout{this};
QLabel m_sign{"Hello World"};
public:
MyWidget(QWidget * parent = nullptr) : QWidget{parent} {
m_topLayout.addWidget(&m_sign, 0, 0);
}
};
你正在傳遞指針,但對象所有權是明確的,所有權沒有變化。 僅僅因為QObject
具有父級並不意味着父級“擁有”它。 如果孩子在父母之前遭到破壞,則所有權停止。 通過使用C ++語義 - 即明確定義的成員構造和破壞順序 - 您可以完全控制子生存期,並且沒有QObject
父級可以干涉。
如果您有一個擁有一個所有者的不可移動對象,請使用std::unique_ptr
並移動它。 這是圍繞您自己的代碼傳遞動態創建的QObject
的方法。 您可以在指向由QObject
父級管理其所有權的位置從指針中刪除它們(如果有的話)。
如果您擁有共享所有權的對象,其生命應該盡快結束(與應用程序終止時相比,或者某些長期存在的對象被破壞),請使用std::shared_ptr
。 確保指針超過用戶。 例如:
class MyData : public QAbstractItemModel { /* ... */ };
class UserWindow : public QWidget {
Q_OBJECT
std::shared_ptr<MyData> m_data; // guaranteed to outlive the view
QTreeView m_view;
public:
void setData(std::shared_ptr<MyData> && data) {
m_data = std::move(data);
m_view.setModel(m_data.data());
}
};
這個例子可能是人為的,因為在Qt中,大多數對象用戶都會觀察對象的destroyed()
信號並對對象的destroyed()
作出反應。 但是,如果例如m_view
是第三方C API對象句柄,無法跟蹤數據對象的生命周期,則這是有道理的。
如果對象的所有權是跨線程共享的,那么使用std::shared_ptr
是必不可少的: destroyed()
信號只能在單個線程中使用。 當您在另一個線程中獲知有關對象刪除的消息時,為時已晚:該對象已被破壞。
第三,當你從工廠方法返回動態創建的對象的實例時,你應該通過一個裸指針返回它們:很明顯,工廠創建了一個供其他人管理的對象。 如果您需要異常安全性,則可以返回std::unique_ptr
。
對於首發,在羅馬,是羅馬人。
QT是在90年代初開發的,並且一次取得了巨大的成功。
不幸的是,隨着時間的推移,QT並沒有真正采用新的功能,因此API本身具有非常古老的C ++風格(我可以說,它是一種Java風格嗎?)
你不能強迫QT突然變成C ++ 14,因為它不是。 在QT方面使用流行的QT約定。 如果這是平台設計目標,請使用原始指針。 不能使用值類型。
但我不認為你使用C ++ 14讓QT工作得那么多。 堅持平台給出的QT習語。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.