chacham15
chacham15

Reputation: 14251

How do you deal with memory management and signal/slots?

I have an object which emits a signal with an object:

MyObj *obj = this->generateObj();
emit newObjSignal(obj);
delete obj;

and I have one or more people who connect to this. The problem is that the delete call gets called before the objects receive the signal. How do I deal with this?

Upvotes: 5

Views: 1757

Answers (3)

SaKabmar_Ashna
SaKabmar_Ashna

Reputation: 144

Just emit another signal in the slot where the signal "newObjSignal(obj)" is consumed then call deletelater.

connect(someobject,SIGNAL(finish()),obj,SLOT(deleteLater()));

Upvotes: 1

Vishesh Handa
Vishesh Handa

Reputation: 1860

While you can use a QSharedPointer, another approach is to not use dynamic memory allocation. The code would therefore be -

MyObj obj = this->generateObj();
emit newObjSignal(obj);

This will obviously result in copies of MyObj being created. Qt generally solves this issue by using implicit sharing or copy-on-write.

In order for your own class to use this implicit sharing mechanism you will have to change the structure of your class and use QSharedData and QSharedDataPointer

class MyObjData : public QSharedData {
public:
    int variable;
};

class MyObj {
    MyObj() : d(new MyObjData) {}
    int foo() { return d->variable; }
private:
    QSharedDataPointer<MyObjData> d;
};

This way copies of MyObj would be very cheap and you can easily pass it over a signal.

This is IMO a lot cleaner than using a QSharedPointer.

Upvotes: 4

Andy Prowl
Andy Prowl

Reputation: 126432

Use smart pointers, so that memory management will be handled automatically and you will be sure you will have:

  1. No dangling pointers;
  2. No memory leaks.

In this case, it seems to me std::shared_ptr<> (or std::tr1::shared_ptr<> or boost::shared_ptr<> if you are not working with C++11) is the correct choice:

#include <memory> // For std::shared_ptr<>
// ...
std::shared_ptr<MyObj> obj(this->generateObj());
emit_new_signal(obj);
// delete obj; // <== No need for this anymore!

Also notice, that the handler functions will have to accept a std::shared_ptr<MyObj> rather than a raw pointer MyObj*, but the code inside those handlers won't have to be changed, because std::shared_ptr provides an overload of operator ->.

Notice that, in general, the use of new is discouraged in C++11, and when possible one should use std::make_shared<> to create shared_ptrs. Thererfore, you may want to rewrite your generateObj() member function so that it returns an std::shared_ptr<MyObj> instead of a MyObj*, and let it use std::make_shared<MyObj>() internally to instantiate the object.

NOTE:

As pointed out by Geier in the comments, Qt has its own smart pointer class QSharedPointer that you may want to use.

Upvotes: 8

Related Questions