4

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

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

我有一个或多个与此相关的人。问题是在对象接收到信号之前调用了删除调用。我该如何处理?

4

3 回答 3

7

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

  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!

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

请注意,一般来说,new在 C++11 中不鼓励使用 of,并且在可能的情况下应该使用std::make_shared<>to create shared_ptrs。因此,您可能需要重写您的generateObj()成员函数,使其返回 astd::shared_ptr<MyObj>而不是 a MyObj*,并让它在std::make_shared<MyObj>()内部使用来实例化对象。

笔记:

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

于 2013-03-23T18:39:16.913 回答
3

虽然您可以使用 a 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 更干净。

于 2013-03-23T19:18:52.697 回答
1

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

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

于 2013-03-23T20:16:15.050 回答