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

I have an object that 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 is called before the objects receive a signal. How can I handle this?

+4
source share
3 answers

Use smart pointers so that memory management is handled automatically and you are sure that you will have:

  • No dangling pointers;
  • There is no memory leak.

In this case, it seems to me that std::shared_ptr<> (or std::tr1::shared_ptr<> or boost::shared_ptr<> if you are not working with C ++ 11) is the right 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 note that the handler functions will need to accept std::shared_ptr<MyObj> , not the raw MyObj* pointer, but the code inside these handlers does not need to be changed, since std::shared_ptr provides operator -> overloading.

Note that in general, using new not recommended in C ++ 11, and if possible, use std::make_shared<> to create shared_ptr s. You might want to rewrite the generateObj() member function so that it returns std::shared_ptr<MyObj> instead of MyObj* and allows it to use std::make_shared<MyObj>() internally to create the object.

Note:

As Geier pointed out in the comments, Qt has its own QSharedPointer smart pointer class , which you can use.

+6
source

While you can use QSharedPointer , another approach is to not use dynamic memory allocation. So the code will be -

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

This will obviously lead to copies of MyObj . Qt usually solves this problem using implicit sharing or copy-to-write.

For your own class to use this implicit exchange 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; }; 

Thus, copies of MyObj will be very cheap, and you can easily transfer them by signal.

This IMO is much cleaner than using QSharedPointer.

+2
source

Just drop another signal into the slot where the "newObjSignal (obj)" signal is consumed, then call deleteelater.

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

+1
source

All Articles