我看到很多关于使用OpenGL进行图形视图的Qt示例。 大多数样本看起来像这样:
MyGraphicsView::MyGraphicsView(......)
{
gl = new QGLWidget();
this->setViewport(gl);
....
其中QGLWidget * gl是MyGraphicsView的成员。
我的问题是在那之后我应该删除" gl"。 我的类继承自QGraphicsView会自动删除吗? 手动删除" gl"在MyGraphicsView中,descructor导致崩溃。
在Qt中真的很难理解哪个对象会被自动删除,哪些对象不会被自动删除。
答案 0 :(得分:1)
在Qt中真的很难理解哪个对象会被自动删除,哪些对象不会被自动删除。
完全没有。你只需要知道两件事:
C ++范围的语义。但是你已经知道了 - 希望如此。
QObject::~QObject()
删除了幸存的孩子:
QObject::~QObject() {
...
for (auto child : children())
delete child;
...
}
显然,如果一个孩子在输入~QObject()
之前被销毁,那么它就不会在父母的children()
列表中,并且不会被双重删除。这在某种程度上似乎让大多数人失望,但如果没有人认为Qt不是魔术,那么就不应该。 Qt做了C ++允许它做的事情。没什么,没什么。
因此,如果其中任何一个为真,对象将被破坏:
您可以在范围内按值保留,例如
class MyGraphicsView : public QGraphicsView {
QOpenGLWidget m_gl;
public:
MyGraphicsView(QWidget * parent = nullptr) : QGraphicsView{parent} {
setViewport(&m_gl); // sets m_gl's parent
Q_ASSERT(m_gl.parent());
}
};
m_gl
成员将在~MyGraphicsView
的正文之后被解构。这是破坏的顺序:
this->~MyGraphicsView()
m_gl.~QOpenGlWidget() // the viewport widget ceases to exist here
this->~QGraphicsView()
this->~QAbstractScrollArea()
this->~QFrame()
this->~QWidget()
this->~QObject() // has no children to delete
它仍然存在,并且在父 ~QObject()
析构函数执行时具有父级。回想一下,所有小部件都是QObject
s。
在上面的示例中,m_gl
对象将在MyGraphicsView::~QObject
运行之前被销毁 - 因此不再存在 - 因此不存在双重破坏的可能性。< / p>
但是你也可以采用过早悲观的指针式方法:
// Don't code like this. It's silly.
class MyGraphicsView : public QGraphicsView {
QOpenGLWidget * m_gl;
public:
MyGraphicsView(QWidget * parent = nullptr) :
QGraphicsView{parent},
m_gl{new QOpenGLWidget}
{
setViewport(m_gl); // sets m_gl's parent
Q_ASSERT(m_gl->parent());
}
~MyGraphicsView() {
Q_ASSERT(m_gl->parent()); // make sure ~QObject will delete the child
}
};
这是破坏的顺序:
this->~MyGraphicsView()
m_gl.~pointer // a trivial destructor of a pointer value
this->~QGraphicsView()
this->~QAbstractScrollArea()
this->~QFrame()
this->~QWidget()
this->~QObject()
for (auto child : children())
delete child
~QOpenGlWidget() // m_gl is long gone at this point!
由于m_gl
成员的破坏是微不足道的,并且对指针本身指向的内容没有做任何事情,QOpenGlWidget
实例会一直存在,直到QObject
析构函数运行,在哪一点迭代其子列表和delete
每个孩子 - 从而删除QOpenGlWidget
实例。
手动删除&#34; gl&#34;在MyGraphicsView中,descructor导致崩溃。
不,它没有,除非你没有告诉我们什么。以下在Qt 4和Qt 5中都可以正常工作。手动删除是无害的,尽管完全没必要:
// https://github.com/KubaO/stackoverflown/tree/master/questions/opengl-viewport-val-39750134
#include <QtGui>
#include <QtOpenGL>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#else
using QOpenGLWidget = QGLWidget;
#endif
// Don't code like this. It's silly.
class MyGraphicsView : public QGraphicsView {
QOpenGLWidget * m_gl = new QOpenGLWidget;
public:
MyGraphicsView(QWidget * parent = nullptr) : QGraphicsView{parent}
{
setViewport(m_gl); // sets m_gl's parent
Q_ASSERT(m_gl->parent());
}
~MyGraphicsView() {
delete m_gl; // completely unnecessary
}
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
MyGraphicsView view;
QGraphicsScene scene;
scene.addText("Hello World");
view.setScene(&scene);
view.show();
return app.exec();
}