If you are not sure what's going on, you can always create your own implicitly shared class to use as value in the QHash, and then output some debug info:
#include <QtGui/QApplication>
#include <QSharedData>
#include <QHash>
#include <QDebug>
{
public:
{ qDebug() << "+ImplSharedData data created"; }
~ImplSharedData()
{ qDebug() << "-ImplSharedData data destroyed"; }
ImplSharedData
(const ImplSharedData
&other
) : QSharedData(other
) { qDebug() << "deep copy of impl. shared data"; }
// ...
};
class ImplSharedClass
{
public:
ImplSharedClass() : d(new ImplSharedData)
{ qDebug() << "+ImplSharedClass object created"; }
~ImplSharedClass() { qDebug() << "-ImplSharedClass object destroyed"; }
ImplSharedClass(const ImplSharedClass &other) : d(other.d)
{ qDebug() << "shallow copy of ImplSharedClass created"; }
ImplSharedClass &operator =(const ImplSharedClass &other)
{
if (this != &other) {
d = other.d;
qDebug() << "shallow copy of ImplSharedClass through assignment";
}
return *this;
}
inline void modify() { d.detach(); } // non-const function that modifies the data
private:
QSharedDataPointer<ImplSharedData> d;
};
struct MyStruct
{
ImplSharedClass shared;
};
#include <QtGui/QApplication>
#include <QSharedData>
#include <QHash>
#include <QDebug>
class ImplSharedData : public QSharedData
{
public:
ImplSharedData() : QSharedData()
{ qDebug() << "+ImplSharedData data created"; }
~ImplSharedData()
{ qDebug() << "-ImplSharedData data destroyed"; }
ImplSharedData(const ImplSharedData &other) : QSharedData(other)
{ qDebug() << "deep copy of impl. shared data"; }
// ...
};
class ImplSharedClass
{
public:
ImplSharedClass() : d(new ImplSharedData)
{ qDebug() << "+ImplSharedClass object created"; }
~ImplSharedClass() { qDebug() << "-ImplSharedClass object destroyed"; }
ImplSharedClass(const ImplSharedClass &other) : d(other.d)
{ qDebug() << "shallow copy of ImplSharedClass created"; }
ImplSharedClass &operator =(const ImplSharedClass &other)
{
if (this != &other) {
d = other.d;
qDebug() << "shallow copy of ImplSharedClass through assignment";
}
return *this;
}
inline void modify() { d.detach(); } // non-const function that modifies the data
private:
QSharedDataPointer<ImplSharedData> d;
};
struct MyStruct
{
ImplSharedClass shared;
};
To copy to clipboard, switch view to plain text mode
then if in main(), you run
MyStruct strukt;
MyStruct strukt2 = strukt;
QHash<int, MyStruct> hash;
hash.insert(1, strukt);
hash.insert(2, strukt2);
MyStruct strukt;
MyStruct strukt2 = strukt;
QHash<int, MyStruct> hash;
hash.insert(1, strukt);
hash.insert(2, strukt2);
To copy to clipboard, switch view to plain text mode
this will generate:
+ImplSharedData data created
+ImplSharedClass object created
shallow copy of ImplSharedClass created
shallow copy of ImplSharedClass created
shallow copy of ImplSharedClass created
-ImplSharedClass object destroyed
-ImplSharedClass object destroyed
-ImplSharedClass object destroyed
-ImplSharedClass object destroyed
-ImplSharedData data destroyed
So the ImplSharedData object is destroyed when the hash falls out of scope. Only one ImplSharedData object exists, but four (4) ImplSharedClass objects, all pointing to the same data.
Btw, MyStruct p = s; will actually invoke the copy-constructor, but if you, on the other hand write:
MyStruct p;
p = s;
MyStruct p;
p = s;
To copy to clipboard, switch view to plain text mode
the assignment operator will be used.
If, instead main() reads something like:
MyStruct *struktPtr1 = new MyStruct;
MyStruct *struktPtr2 = new MyStruct(*struktPtr1);
QHash<int, MyStruct *> hash2;
hash2.insert(1, struktPtr1);
hash2.insert(2, struktPtr2);
MyStruct *struktPtr1 = new MyStruct;
MyStruct *struktPtr2 = new MyStruct(*struktPtr1);
QHash<int, MyStruct *> hash2;
hash2.insert(1, struktPtr1);
hash2.insert(2, struktPtr2);
To copy to clipboard, switch view to plain text mode
you get:
+ImplSharedData data created
+ImplSharedClass object created
shallow copy of ImplSharedClass created
Here nothing gets destroyed when the hash is going out of scope, so like you said you need to do:
MyStruct *struktPtr1 = new MyStruct;
MyStruct *struktPtr2 = new MyStruct(*struktPtr1);
QHash<int, MyStruct *> hash2;
hash2.insert(1, struktPtr1);
hash2.insert(2, struktPtr2);
qDeleteAll(hash2);
MyStruct *struktPtr1 = new MyStruct;
MyStruct *struktPtr2 = new MyStruct(*struktPtr1);
QHash<int, MyStruct *> hash2;
hash2.insert(1, struktPtr1);
hash2.insert(2, struktPtr2);
qDeleteAll(hash2);
To copy to clipboard, switch view to plain text mode
This gives:
+ImplSharedData data created
+ImplSharedClass object created
shallow copy of ImplSharedClass created
-ImplSharedClass object destroyed
-ImplSharedClass object destroyed
-ImplSharedData data destroyed
...and all is well.
--
You can also call the modify() function to see what happens when the data is detached (copy-on-write). For example:
struktPtr1->shared.modify();
struktPtr1->shared.modify();
To copy to clipboard, switch view to plain text mode
Bookmarks