This article was first published on my homepage http://www.devbean.info, and will be published directly there. Now there is a Flex 4 and "from C + + to Objective-c" series, thank you for your support!
Strongly typed languages always explicitly or implicitly contain type information for objects when they are created. That is, a strongly typed language is always associated with the type of the object when it allocates the object memory space. In contrast, weakly typed languages do not do so. After allocating memory space, there are two ways to free up space: by hand, or by using the garbage collector. C + + requires developers to manually free up memory space. The advantage of this is that the developer has complete control of the interior and knows when the release is appropriate. Java uses the garbage collector. It will have a thread in the background to constantly see which objects are not being used and can be recycled based on certain algorithms. This frees the developer from the underlying implementation and focuses on the business logic.
This article focuses on QT memory management, which uses the QT mechanism to implement a simple garbage collector.
C + + memory management mechanism
C + + requires developers to manage their own memory. There are three types of strategies:
- Let the created object delete its own sub-object (the sub-object referred to here refers to the object's properties, not the subclass, similar to the following);
- Let the last object handle the delete;
- Regardless of memory.
The last one is usually a "memory leak" and is considered a bug. So now we are going to choose which of the previous two is more appropriate. Sometimes, delete creates an object that is much simpler than all its child objects, and sometimes finding the last object can be quite difficult.
Qt Memory management mechanism
Qt can maintain the hierarchy of objects internally. For visual elements, this hierarchy is the child component's relationship to the parent component, and for non-visual elements, it is the dependency of one object to another. In Qt, deleting a parent object deletes its child objects together. This helps reduce memory problems by 90%, creating a mechanism similar to garbage collection.
Qpointer
Qpointer is a template class. It is similar to a normal pointer, except that Qpointer can monitor dynamically allocated objects and update them when the object is deleted.
- Qpointer behaves like a normal pointer
- Qdate *mydate = new Qdate (Qdate::currentdate ());
- Qpointer mypointer = MyData;
- Mydate->year (); ///2005
- Mypointer->year (); ///2005
- Qpointer will behave differently when the object is delete
- Delete mydate;
- if (mydate = = NULL)
- printf ("clean pointer");
- Else
- printf ("dangling pointer");
- Output dangling pointer
- if (Mypointer.isnull ())
- printf ("clean pointer");
- Else
- printf ("dangling pointer");
- Output clean pointer
Note the above code. After a raw pointer delete, its value is not set to NULL, and therefore becomes a wild pointer. However, Qpionter does not have this problem.
Qobjectcleanuphandler
The Qt object Cleaner is an important part of implementing automatic garbage collection. It can register many sub-objects and automatically delete all child objects when they are deleted. At the same time, it can also identify if a child object has been deleted, thereby removing it from its list of child objects. This class can be used for cleanup of classes that are not in the same hierarchy, for example, when a button is pressed to close many windows, because the window's parent property is not likely to be set to a button in another window, this class can be quite handy when used.
- Create an instance
- Qobjectcleanuphandler *cleaner = new Qobjectcleanuphandler;
- Create window
- Qpushbutton *w = new Qpushbutton ("Remove Me");
- W->show ();
- Register the first button
- Cleaner->add (w);
- If the first button is clicked, delete itself
- Connect (w, SIGNAL (clicked ()), W, SLOT (Deletelater ()));
- Create a second button, note that this button does not have any action
- w = new Qpushbutton ("nothing");
- Cleaner->add (w);
- W->show ();
- Create a third button to delete all
- w = new Qpushbutton ("Remove All");
- Cleaner->add (w);
- Connect (w, SIGNAL (clicked ()), cleaner, SLOT (Deletelater ()));
- W->show ();
In the code above, three windows with only one button are created. When the first button is clicked, it will delete itself (through the Deletelater () slot), at which point the cleaner automatically clears it from its own list. When the third button is clicked, The Cleaner is deleted, which removes all windows that are not closed at the same time.
Qt Garbage Collection
As objects become more complex, it is difficult to decide when to make a delete operation when this object is used in many places. Fortunately, Qt has a good garbage collection mechanism for all classes that inherit from Qobject. There are many ways to implement garbage collection, the simplest is the reference count, and the other is to save all objects. We will explain these two implementations in detail below.
Reference count
The application count is the simplest garbage collection implementation: Each object is created, the counter is incremented by 1, minus 1 for each deletion.
- Class Countedobject
- {
- Public
- Countedobject ()
- {
- ctr=0;
- }
- void Attach ()
- {
- ctr++;
- }
- void Detach ()
- {
- ctr--;
- if (Ctr <= 0)
- Delete this ;
- }
- Private
- Int Ctr;
- };
Each child object should call the Attach () function after it is created, and the counter will be incremented by 1, and the detach () update counter should be called when it is deleted. However, this class is primitive and does not use Qt's convenient mechanism. Below we give a Qt version of the implementation:
- Class Countedobject: Public qobject
- {
- Q_object
- Public
- Countedobject ()
- {
- ctr=0;
- }
- void Attach (Qobject *obj)
- {
- ctr++;
- Connect (obj, SIGNAL (destroyed (qobject*)), SLOT (Detach ()));
- }
- Public Slots:
- void Detach ()
- {
- ctr--;
- if (Ctr <= 0)
- Delete this ;
- }
- Private
- Int Ctr;
- };
We use Qt's signal slot mechanism to automatically reduce the value of the counter when the object is destroyed. However, our implementation does not prevent the object from being created by calling two times attach ().
Record owner
A more appropriate implementation is not only to remember that several objects hold references, but also to remember which objects are. For example:
- Class Countedobject: Public qobject
- {
- Public
- Countedobject ()
- {
- }
- void Attach (Qobject *obj)
- {
- //Check owner
- if (obj = = 0)
- return;
- //Check whether you have added
- if (owners.contains (obj))
- return;
- //Registration
- Owners.append (obj);
- Connect (obj, SIGNAL (destroyed (qobject*)), SLOT (Detach (qobject*)));
- }
- Public Slots:
- void Detach (Qobject *obj)
- {
- //Delete
- Owners.removeall (obj);
- //If the last object is also deleted, delete itself
- if (owners.size () = = 0)
- Delete this ;
- }
- Private
- Qlist owners;
- };
Now our implementation has been able to prevent one object from calling Attach () and detach () multiple times. However, another problem is that we cannot guarantee that the object will call the Attach () function for registration. After all, this is not a C + + built-in mechanism. One solution is to redefine the new operator (this implementation is also complex, but avoids the case where an object does not call attach () registration).
This article is from Devbean ' s world:http://www.devbean.info.
Please indicate the original source of the article when reprinted: Http://www.devbean.info/2011/03/qt_memory_management/.
http://devbean.blog.51cto.com/448512/526734
Qt Memory management mechanism