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

时间:2013-03-23 18:36:14

标签: c++ qt memory-management

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

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

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

3 个答案:

答案 0 :(得分:7)

使用智能指针,以便自动处理内存管理,并确保您拥有:

  1. 没有悬空指针;
  2. 没有内存泄漏。
  3. 在这种情况下,在我看来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*,但这些处理程序中的代码不必更改,因为{{1}提供std::shared_ptr的重载。

    请注意,通常,在C ++ 11中不鼓励使用operator ->,如果可能,应使用new创建std::make_shared<>。因此,您可能希望重写shared_ptr成员函数,使其返回generateObj()而不是std::shared_ptr<MyObj>,并让它在内部使用MyObj*来实例化对象。 / p>

    注意:

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

答案 1 :(得分:2)

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

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

这显然会导致创建MyObj的副本。 Qt通常使用implicit sharing或copy-on-write来解决此问题。

为了让您自己的班级使用这种隐式共享机制,您必须更改班级的结构并使用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要快得多。

答案 2 :(得分:1)

只是在消耗信号“newObjSignal(obj)”的插槽中发出另一个信号,然后调用deletelater。

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