我的宠物项目已经到了我应该开始跟踪指针寿命的地步,我正在尝试为它开发一些系统。遗憾的是,由于Qt API本身在任何情况下都使用裸指针,因此在任何地方使用智能指针的流行建议都不适用。所以,我想到的是:
-
对于Qt、所有的一切
- 在本地使用裸指针
- 在函数之间也裸体传递它们
- 将它们存储为子类CCD_ 1,使CCD_
-
对于我干净拥有的所有东西,请按照建议使用智能指针。我将在这里使用
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
父级无法干预。
如果您有一个所有者的不可移动对象,请使用QPointer
0并将其四处移动。这是围绕您自己的代码传递动态创建的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()
信号,并对对象的破坏做出反应。但是,如果例如m_view
是无法跟踪数据对象生命周期的第三方C API对象句柄,则这是有意义的。
如果对象的所有权在线程之间共享,那么std::shared_ptr
的使用是必不可少的:destroyed()
信号只能在单个线程中使用。当您在另一个线程中得知对象删除时,已经太晚了:对象已经被销毁。
第三,当您从工厂方法返回动态创建的对象的实例时,您应该通过裸指针返回它们:很明显,工厂创建了一个对象供其他人管理。如果您需要异常安全,您可以返回std::unique_ptr
。
对于初学者来说,在罗马,是罗马人
QT是在90年代早期开发的,在当时取得了巨大成功
不幸的是,随着时间的推移,QT并没有真正采用新的功能,因此API本身有非常古老的C++风格(我可以说是Java风格吗?)
你不能强迫QT突然变成C++14,因为它不是。当涉及到QT时,请使用流行的QT约定。如果这是平台设计的目标,请使用原始指针。如果不能,请使用值类型。
但我不认为QT能在C++14中发挥那么大的作用。按照平台给出的QT习惯用法进行粘贴。