首先,尽可能按价值持有事物。查看 的每次使用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);
}
};
您正在传递指针,但对象所有权是明确的,并且所有权没有变化。仅仅因为 aQObject
有父级并不意味着父级“拥有”它。如果子项在父项之前被销毁,则所有权将终止。通过使用 C++ 语义(即成员构造和销毁的明确定义的顺序),您可以完全控制子生命周期,并且没有QObject
父节点干预。
如果您有一个所有者的不可移动对象,请使用std::unique_ptr
并移动它。QObject
这是在您自己的代码周围传递动态创建的 s 的方式。您可以在将其所有权由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()
信号并对对象的破坏做出反应。m_view
但是,如果第三方 C API 对象句柄无法跟踪数据对象的生命周期,则这是有道理的。
如果对象的所有权是跨线程共享的,那么使用std::shared_ptr
是必不可少的:destroyed()
信号只能在单个线程内使用。当您在另一个线程中收到有关删除对象的通知时,为时已晚:该对象已被销毁。
第三,当您从工厂方法返回动态创建的对象的实例时,您应该通过裸指针返回它们:很明显,工厂创建了一个对象供其他人管理。如果您需要异常安全,则可以返回 a std::unique_ptr
。