memory management
-
hello,
In one QObject derived class I have a loop where i dinamically create Obj objects (QObject derived) , set attributes and add them to a member container (QVariantList) using QVariant::fromValue
myObjectList.clear() // QVariantList // loop Obj*o = new Obj(this); // o->setValue(6); myObjectList.append(QVariant::fromValue(o)); // myObjectList is a QVariantList type member variable // endloop emit myObjectListChanged()
every time i enter this method/loop i need to empty myObjectList and re-create the Obj objects to store them back in my list.
But calling myObjectList.clear() will not delete the Obj* objects ? is that right?
Obj objects will only be deleted when this is deleted because i create them like this Obj*o = new Obj(this); ?thank you
-
@ODБOï said in memory management:
But calling myObjectList.clear() will not delete the Obj* objects ? is that right?
Yes
You can use https://doc.qt.io/qt-5/qtalgorithms.html#qDeleteAll-1
-
@jsulm does QVariant::fromValue return a copy of the pointer in this case ? and is there an implicit back conversion ?
Or does callingdelete
on a Variant from a pointer actually call delete on the pointer and not on the QVariant !?Lots of magic going on here 🙈
-
@ODБOï said in memory management:
But calling myObjectList.clear() will not delete the Obj* objects ? is that right?
Yes.
Obj objects will only be deleted when this is deleted because i create them like this Obj*o = new Obj(this); ?
Or explicitly, or via a signal-slot connection, but yes.
@J-Hilk said in memory management:
does QVariant::fromValue return a copy of the pointer in this case ?
It does.
and is there an implicit back conversion ?
I don't believe so. Back convert to what?
QObject *
,void *
,int *
?Or does calling delete on a Variant from a pointer actually call delete on the pointer and not on the QVariant !?
You can test this, but as
QVariant
or any other Qt type I'm aware of doesn't overload the delete operator I imagine you're going to get a compile-time error. -
ok, ok, I see 😜
I'll go and test it myself...
class MyObj : public QObject { Q_OBJECT public: explicit MyObj (QObject *parent = nullptr) : QObject(parent){} ~MyObj() { qDebug("Destroy ME!!!!"); } }; int main(int argc, char *argv[]) { Q_UNUSED(argc); Q_UNUSED(argv); QVariantList myVariantList; for(int i{0},j{10}; i < j; i++) myVariantList.append(QVariant::fromValue(new MyObj())); qDeleteAll(myVariantList); qDebug("End of main"); // QApplication app(argc, argv); // return a.exec(); } #include "main.moc"
results int he compiler error:
cannot delete expression of type 'const QVariant'
Well, so we'll have to use our own deleteall. One that also clears, as that is what we actually want. Delete & Clear:
class MyObj : public QObject { Q_OBJECT public: explicit MyObj (QObject *parent = nullptr) : QObject(parent){} ~MyObj() override { qDebug("Destroy ME!!!!"); } }; template <typename Class> inline void deleteAllAndClear(QVariantList &list) { for(const QVariant &v : list){ delete qvariant_cast<Class*>(v); } list.clear(); } int main(int argc, char *argv[]) { Q_UNUSED(argc) Q_UNUSED(argv) QVariantList myVariantList; for(int i{0},j{10}; i < j; i++) myVariantList.append(QVariant::fromValue(new MyObj())); qDebug() << "size of list" << myVariantList.size(); deleteAllAndClear<MyObj>(myVariantList); qDebug() << "size of list" << myVariantList.size(); qDebug("End of main"); // QApplication app(argc, argv); // return a.exec(); } #include "main.moc"
Output:
size of list 10
Destroy ME!!!!
Destroy ME!!!!
Destroy ME!!!!
Destroy ME!!!!
Destroy ME!!!!
Destroy ME!!!!
Destroy ME!!!!
Destroy ME!!!!
Destroy ME!!!!
Destroy ME!!!!
size of list 0
End of main -
hi
Thank you very much for all your inputs@kshegunov said in memory management:
Something I forgot to ask, why not keep the object list as a regular one (e.g. QList<QObject *>) and put the QVector/QList in the variant whenever you need to?
You are right it much simpler to have a member QList<QObject *> and return QVariant list only when i need it.
Thats what i did.Thank you