Inside QT series (12): parent-child relationship between QT objects

Source: Internet
Author: User
Tags valgrind

Many C/C ++ beginners often make the mistake of using malloc and new to allocate a piece of memory but forget to release it, resulting in Memory leakage. The QT object model provides a parent-child relationship between QT objects. When many objects establish this parent-child relationship in a certain order, they are organized into a tree. When deleting a parent object, QT's object model ensures that all its sub-objects, as well as sun objects, are automatically deleted, this prevents Memory leakage.

Everything has both positive and negative effects. This mechanism seems quite good, but it will cause troubles for many beginners of QT. The questions I often give to others are:1. When should I delete a new QT object? 2. Is there a bug in the destructor of QT? 3. Why does a normal delete QT object produce a segment fault?And so on. This article is a detailed explanation of this issue.

Each QT object has a linked list, which stores pointers to all its sub-objects. When creating a new QT object, if you specify another QT object as the parent object of this object, then the parent object will add the pointer of this Sub-object to its sub-Object List. In addition, for any QT object, You can reset its parent object at any time of its lifecycle through the setparent function. When a parent object is deleted, it automatically deletes all its sub-objects. When a child object is deleted, it will delete itself from its parent object sub-Object List.

Qwidget is the base class of all interface objects displayed on the screen. It extends the parent-child relationship of QT objects. A widget object naturally becomes a child widget of its parent widget object and is displayed in its parent widget's coordinate system. For example, the button on a dialog box (DIALOG) should be a sub-widget of the dialog box.

For the new and delete functions of the QT object, the following is an example.

For example, the following code is correct:

Int main ()
{
Qobject * objparent = new qobject (null );
Qobject * objchild = new qobject (objparent );
Qobject * objchild2 = new qobject (objparent );
Delete objparent;
}

We use a graph to describe the relationship between the three objects:

In the code snippet above, objparent is the parent object of objchild. In the objparent object, there is a subobject linked list, which stores pointers of all its sub-objects. Here, the pointer of objchild and objchild2 is saved. At the end of the Code, only one object objparent is deleted. The destructor of the objparent object will traverse its sub-Object List and put all its sub-objects (objchild and objchild2) delete one by one. Therefore, the above Code is safe and will not cause memory leakage.

If we change the above Code to this, it is also correct:

Int main ()
{
Qobject * objparent = new qobject (null );
Qobject * objchild = new qobject (objparent );
Qobject * objchild2 = new qobject (objparent );
Delete objchild;
Delete objparent;
}

In this Code, we only look at the difference from the previous code, that is, before deleting the objparent object, delete the objchild object first. When deleting an objchild object, the objchild object will automatically delete itself from the sub-object linked list of the objparent object. That is to say, after the object is deleted, the objparent object has only one child object (objchild2. Then, when you delete the objparent object, the objchild2 object is automatically deleted. Therefore, this code is safe.

Qt's design is unfriendly to some debugging tools, such as valgrind. For example, in the above Code, the valgrind tool considers that the objchild2 object is not correctly deleted when analyzing the code, and reports that the Code contains Memory leakage. Haha, we know that this report is incorrect.

Let's take a look at this piece of code:

Int main ()
{
Qwidget window;
Qpushbutton quit ("exit", & window );
}

In this Code, we created two widget objects, window and quit. They are all QT objects, because qpushbutton is derived from qwidget, qwidget is derived from qobject. The relationship between the two objects is that the window object is the parent object of the quit object, because they will all be allocated on the stack, will the quit object be destructed twice? We know that the variables declared in a function body will be destructed when the function exits. In this code, both window and quit objects are called when the function exits. If the window destructor is called first, it will delete the quit object. Then the quit destructor will be called again, and the program will go wrong. This is not the case. According to the C ++ standard, the calling sequence of the destructor of local objects is the opposite to that of their constructor. In this Code, the quit object's destructor will be called before the window object's destructor, the quit object does not exist and will not be destructed twice.

If we change the code to this way, an error will occur. Let's take a look at the previous explanation.

Int main ()
{
Qpushbutton quit ("exit ");
Qwidget window;
Quit. setparent (& window );
}

However, when writing a program, we must also pay attention to one item. Do not delete the sub-object twice. Just like the code above, the program must be crash.

Finally, Let's combine QT source code to see how the parent/child relationship is implemented.

In the first part of this topic, "Object Data Storage", we have mentioned that the base class of private data members of all QT objects is the qobjectdata class. The definition of this class is as follows:

Typedef qlist <qobject *> qobjectlist;
Class qobjectdata
{
Public:
Qobject * parent;
Qobjectlist children;
// Ignore other member Definitions
};

We can see that the pointer to parent is defined here, and the list of sub-objects is saved. In fact, setting an object as the parent object of another object is nothing more than operating the two data. Set the parent variable in the child object to point to its parent object, and add the Sub-object pointer to the children list of the parent object. Of course, what I am talking about here is very simple. The actual code is much more complicated, including many conditional judgments. If you are interested, you can read the source code of QT on your own.

========================================================== ====================================
Statement:
Inside QT series is an original technical article (http://www.qkevin.com.
This series of columns can be reproduced at will, but the statement and original address of each article must be kept.
The Copyright reserved by the author shall not be used for any commercial purposes without the consent of the author

Total index of the column in inside QT series: http://www.qkevin.com/qt
Original address: http://www.qkevin.com/archives/93

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.