2013-03-23 76 views
4

我有一个发出信号与对象的对象:你如何处理内存管理和信号/插槽?

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

,我有谁连接到这一个或更多的人。问题是在对象接收信号之前调用删除调用。我如何处理这个问题?

+1

,信号/槽机制是通过缺省同步(即,没有问题,因为删除被称为当所有时隙都已经被称为),除非你是跨线程信令(或显式地指定一个延迟连接政策)。如果您的确在跨线程发信号,则必须小心使用智能指针解决方案,因为它们可能不是线程安全的。 – 2013-03-23 20:21:45

回答

6

使用智能指针,使内存管理会自动处理,你会相信你将有:

  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,你可能要使用。

+2

Qt也有自己的共享指针,如[QSharedPointer](http://qt-project.org/doc/qt-4.8/qsharedpointer.html) – Geier 2013-03-23 18:41:33

+0

@Geier:好的,我不熟悉Qt,但我会添加这个信息给我的答案。谢谢你 – 2013-03-23 18:42:53

+0

你从c得到的对象(即malloc'ed结构)有什么作用? – chacham15 2013-03-23 19:05:56

2

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

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

这显然会导致创建副本MyObj。 Qt通常通过使用implicit sharing或写时复制来解决此问题。

为了让自己的类使用这种隐含的共享机制,你将不得不改变你的类的结构和使用QSharedDataQSharedDataPointer

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

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

这样的MyObj副本会很便宜,你可以轻松传递信号。

这是IMO比使用QSharedPointer更清洁。

1

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

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

Qt中