Qt的内存管理?

Mar*_*tin 91 c++ memory qt object

我对Qt很新,我想知道一些关于内存管理和对象生命的基本知识.我什么时候需要删除和/或销毁我的对象?这是否自动处理?

在下面的示例中,我需要删除哪些对象?销毁myOtherClass时实例变量会发生什么myClass?如果我不删除(或破坏)我的对象会发生什么?记忆会有问题吗?

MyClass.h

class MyClass
{

public:
    MyClass();
    ~MyClass();
    MyOtherClass *myOtherClass;
};
Run Code Online (Sandbox Code Playgroud)

MyClass.cpp

MyClass::MyClass() {
    myOtherClass = new MyOtherClass();

    MyOtherClass myOtherClass2;

    QString myString = "Hello";
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样,这是一个非常新手很容易的东西,但我在哪里可以轻松地了解这一点?

Deb*_*ski 96

如果使用QObjects 构建自己的层次结构,即QObject使用父级初始化所有新创建的s,

QObject* parent = new QObject();
QObject* child = new QObject(parent);
Run Code Online (Sandbox Code Playgroud)

那就足够deleteparent,因为parents析构函数会照顾到毁灭child.(它通过发出信号来实现,因此即使在child父母之前手动删除它也是安全的.)

您也可以先删除孩子,顺序无关紧要.有关订单确实重要的示例,请参阅有关对象树的文档.

如果你MyClass不是孩子QObject,你将不得不使用简单的C++做事方式.

另请注意,QObjects 的父子层次结构通常独立于C++类层次结构/继承树的层次结构.这意味着,指定的子节点不需要是其父节点的直接子类.任何(子类)QObject都足够了.

但是,由于其他原因,构造函数可能会施加一些约束; 例如in QWidget(QWidget* parent=0),其中父母必须是另一个QWidget,因为例如可见性标志,并且因为你做那样的基本布局; 但对于Qt的层次结构系统,一般情况下,您可以将任何一个QObject作为父级.

  • `(它通过发出信号来做到这一点,所以即使你在父母之前手动删除孩子也是安全的.)` - >这不是它安全的原因.在Qt 4.7.4中,QObject子项被直接删除(通过`delete`,参见qobject.cpp,第1955行).首先删除子对象是安全的原因是QObject在被删除时告诉其父对象忘记它. (21认同)
  • 我想补充一点,你必须确保后代的析构函数是虚拟的,因为这是真的.如果`ClassB`继承自`QObject`并且`ClassC`继承自`ClassB`,那么如果`ClassB`的析构函数是虚拟的,那么`ClassC`将只被Qt的父子关系正确销毁. (5认同)
  • @Phlucious QObject的析构函数已经是虚拟的,这使得每个子类的析构函数都是自动虚拟的. (2认同)

Aus*_*tin 47

我想通过指出所有权的概念在Qt中非常重要来扩展Debilski的答案.当A类承担B类的所有权时,删除A类时删除B类.在某些情况下,一个对象成为另一个对象的所有者,而不仅仅是在创建对象并指定其父对象时.

例如:

QVBoxLayout* layout = new QVBoxLayout;
QPushButton someButton = new QPushButton; // No owner specified.
layout->addWidget(someButton); // someButton still has no owner.
QWidget* widget = new QWidget;
widget->setLayout(layout); // someButton is "re-parented".
                           // widget now owns someButton.
Run Code Online (Sandbox Code Playgroud)

另一个例子:

QMainWindow* window = new QMainWindow;
QWidget* widget = new QWidget; //widget has no owner
window->setCentralWidget(widget); //widget is now owned by window.
Run Code Online (Sandbox Code Playgroud)

因此,经常检查文档,它通常指定方法是否会影响对象的所有权.

如Debilski所述,这些规则仅适用于从QObject派生的对象.如果您的类不是从QObject派生的,那么您必须自己处理破坏.

  • 嗯,QPushButton*someButton = new QPushButton之间存在巨大差异; 和QPushButton someButton;.前者将在堆上分配对象,而后者将在堆栈上分配它.QPushButton*someButton = new QPushButton()之间没有区别; 和QPushButton someButton = new QPushButton;,它们都会调用对象的默认构造函数. (3认同)
  • 您需要阅读有关动态分配,对象范围和RAII的信息.在普通C++的情况下,您应尽可能在堆栈上分配对象,因为当对象超出范围时会自动销毁对象.对于类成员,最好由于性能而在堆上分配对象.每当你想要一个对象"比"一个函数/方法的执行"寿命"时,你应该在堆上分配对象.同样,这些是非常重要的主题,需要一些阅读. (3认同)

yes*_*aaj 7

父(QObject对象或其派生类)具有指向其子项的指针列表(QObject /其派生).父节点将在父节点被删除时删除其子列表中的所有对象.您可以使用QObject的此属性使子对象在删除父对象时自动删除.可以使用以下代码建立关系

QObject* parent = new QObject();
QObject* child = new QObject(parent);
delete parent;//all the child objects will get deleted when parent is deleted, child object which are deleted before the parent object is removed from the parent's child list so those destructor will not get called once again.
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以使用smartpointer在Qt中管理内存.以下文章描述了Qt中的各种智能指针. https://blog.qt.digia.com/blog/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have/