你如何处理内存管理和信号/插槽

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

本文关键字:管理 信号 插槽 内存 何处理 处理      更新时间:2023-10-16

我有一个用对象发出信号的对象:

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

和我有一个或多个连接到这个的人。问题是在对象接收到信号之前调用了delete调用。我该如何处理呢?

使用智能指针,这样内存管理将自动处理,您将确保您将有:

  1. 没有悬浮指针;
  2. 没有内存泄漏。

在这种情况下,在我看来,std::shared_ptr<>(或std::tr1::shared_ptr<>boost::shared_ptr<>,如果你不使用c++ 11)是正确的选择:

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

还要注意,处理程序函数必须接受std::shared_ptr<MyObj>而不是原始指针MyObj*,但是这些处理程序内部的代码不必更改,因为std::shared_ptr提供了operator ->的重载。

注意,一般来说,在c++ 11中不鼓励使用new,如果可能的话,应该使用std::make_shared<>来创建shared_ptr。因此,您可能需要重写generateObj()成员函数,使其返回std::shared_ptr<MyObj>而不是MyObj*,并让它在内部使用std::make_shared<MyObj>()来实例化对象。

注意:

正如Geier在评论中指出的那样,Qt有自己的智能指针类QSharedPointer,您可能想要使用。

虽然可以使用QSharedPointer,但另一种方法是不使用动态内存分配。因此代码应该是-

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

这显然会导致创建MyObj的副本。Qt通常通过使用隐式共享或写时复制来解决这个问题。

为了让你自己的类使用这种隐式共享机制,你必须改变你的类的结构,并使用QSharedDataQSharedDataPointer

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

这样,MyObj的副本将非常便宜,并且您可以轻松地通过信号传递它。

在我看来,这比使用QSharedPointer干净多了。

只需在信号"newObjSignal(obj)"被消耗的槽中发出另一个信号,然后调用deleteelater。

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