sig*_*gil 3 c++ qt pointers qpointer
我的宠物项目已经到了我应该开始跟踪指针寿命的地步,我正在尝试为其开发一些系统。遗憾的是,流行的到处使用智能指针的建议并不适用,因为 Qt API 本身在任何情况下都使用裸指针。所以,我想到的是:
对于 Qt 拥有的一切,
QPointer,在转换为裸之前进行isNull()检查。对于我完全拥有的所有东西,请按照建议使用智能指针。我将使用std::这里的版本。
令我烦恼的案子。对于切换所有权的对象(例如从布局中添加/删除的小部件)
delete在适当的时候手动进行。建议、意见、建议?我自己不太喜欢这个方案。
首先,尽可能按价值持有事物。带着怀疑的态度查看 的new每次使用- 您必须证明每个动态对象创建的合理性。如果子对象与父对象具有相同的生命周期,则按值保存是理所当然的。例如:make_uniquemake_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);
}
};
Run Code Online (Sandbox Code Playgroud)
您正在传递指针,但对象所有权是明确的,并且所有权没有变化。仅仅因为 aQObject有父对象并不意味着父对象“拥有”它。如果孩子在父母之前被摧毁,则所有权终止。通过使用 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());
}
};
Run Code Online (Sandbox Code Playgroud)
这个例子可能是人为的,因为在 Qt 中大多数对象用户都会观察对象的destroyed()信号并对对象的销毁做出反应。m_view但是,如果eg是无法跟踪数据对象生命周期的第三方C API 对象句柄,则这是有意义的。
如果对象的所有权是跨线程共享的,那么使用std::shared_ptr是必不可少的:destroyed()信号只能在单个线程中使用。当您在另一个线程中收到有关对象删除的通知时,为时已晚:该对象已经被销毁。
第三,当您从工厂方法返回动态创建的对象的实例时,您应该通过裸指针返回它们:很明显,工厂创建一个对象供其他人管理。如果你需要异常安全,你可以返回 astd::unique_ptr来代替。