[ fromfile: generics.xml id: sortedmapexample ]
As mentoned earlier, QMap is an associative array that maintains key sorting-order as items are added and removed. Key-based insertions and deletions are fast (log(n)) and iteration is done in key order.
QMap is a value container, but
pointers are simple values, so you can use a QMap to store
pointers to heap allocated QObject
s.
By default, however, value containers do not manage heap objects so, to avoid memory leaks, you must ensure
they are deleted at the proper time.
Figure 11.3
describes a class that extends a QMap to contain information
about textbooks.
By deriving from QMap, the entire public
interface of QMap becomes part of the public
interface of TextbookMap
.
We added only a destructor plus two convenience functions to facilitate adding and displaying Textbooks
in the container.
This convenience also creates some problems as you can see next.
TextbookMap
consists of <key,value> pairs with ISBN numbers as keys and
Textbook
pointers as values.
Example 11.8 shows the class definitions.
Example 11.8. src/containers/qmap/textbook.h
#ifndef _TEXTBOOK_H_ #define _TEXTBOOK_H_ #include <QObject> #include <QString> #include <QMap> class Textbook : public QObject { Q_OBJECT public: Textbook(QString title, QString author, QString isbn, uint year); [ . . . . ] private: QString m_Title, m_Author, m_Isbn; uint m_YearPub; }; /* Managed collection of pointers */ class TextbookMap : public QMap<QString, Textbook*> { public: ~TextbookMap(); void add(Textbook* text); QString toString() const; }; #endif
In Example 11.9, the destructor uses qDeleteAll()
on the values()
of the QMap, deleting each pointer.
This is necessary for a value container to manage its objects.
Example 11.9. src/containers/qmap/qmap-example.cpp
[ . . . . ] TextbookMap::~TextbookMap() { qDebug() << "Destroying TextbookMap ..." << endl; qDeleteAll(values()); clear(); } void TextbookMap::add(Textbook* text) { insert(text->getIsbn(), text); } QString TextbookMap::toString() const { QString retval; QTextStream os(&retval); ConstIterator itr = constBegin(); for ( ; itr != constEnd(); ++itr) os << '[' << itr.key() << ']' << ": " << itr.value()->toString() << endl; return retval; }
It is important to understand, as you can see in the client code shown in Example 11.10, that
when you remove()
a pointer from the TextbookMap
you also remove its responsibility for managing that pointer.
Once you remove it, you have the responsibility for
deleting that pointer! In other words, client code can easily produce memory leaks.
The same problem arises with other QMap member
functions (e.g., QMap::erase()
and QMap::take()
).
You can diminish these particular problems by hiding
the dangerous QMap functions with TextbookMap
versions that remove and delete or reparent no longer needed Textbook
pointers.
Another (perhaps safer) option would be to use private
derivation instead of
public
derivation.
Then the TextbookMap
public interface would contain only safe public
member
functions that you (carefully) defined.
Example 11.10. src/containers/qmap/qmap-example.cpp
[ . . . . ] int main() { Textbook* t1 = new Textbook("The C++ Programming Language", "Stroustrup", "0201700735", 1997); Textbook* t2 = new Textbook("XML in a Nutshell", "Harold","0596002920", 2002); Textbook* t3 = new Textbook("UML Distilled", "Fowler", "0321193687", 2004); Textbook* t4 = new Textbook("Design Patterns", "Gamma", "0201633612",1995); { TextbookMap m; m.add(t1); m.add(t2); m.add(t3); m.add(t4); qDebug() << m.toString(); m.remove (t3->getIsbn()); } qDebug() << "After m has been destroyed we still have:\n" << t3->toString(); return 0; }
When TextbookMap::ShowAll()
iterates through the container, you can see from
the output in Example 11.11 that the Textbooks
have been placed in order by ISBN (the key).
Example 11.11. src/containers/qmap/qmap-example-output.txt
src/containers/qmap> ./qmap [0201633612]:Title: Design Patterns; Author: Gamma; ISBN: 0201633612; Year: 1995 [0201700735]:Title: The C++ Programming Language; Author: Stroustrup; ISBN: 0201700735; Year: 1997 [0321193687]:Title: UML Distilled; Author: Fowler; ISBN: 0321193687; Year: 2004 [0596002920]:Title: XML in a Nutshell; Author: Harold; ISBN: 0596002920; Year: 2002 Destroying TextbookMap ... After m has been destroyed we still have: Title: UML Distilled; Author: Fowler; ISBN: 0321193687; Year: 2004 src/containers/qmap>
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |