2013-03-23 7 views
4

나는 객체와 신호를 방출하는 물체가 있습니다메모리 관리 및 신호/슬롯을 어떻게 처리합니까?

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

을하고 나는이에 연결 한 명 이상의 사람이있다. 문제는 객체가 신호를 받기 전에 delete 호출이 호출된다는 것입니다. 이 문제를 어떻게 처리합니까?

+1

, 신호/슬롯 메커니즘은, (삭제가 호출 될 때 모든 슬롯이 이미이라고되어 ​​있기 때문에, 즉 문제) 기본적으로 동기입니다 당신이 스레드를 통해 신호된다 (또는 명시 적으로 지연 연결을 지정하지 않는 한 정책). 실제로 스레드를 통해 신호를 보내는 경우에는 스레드 안전하지 않을 수 있으므로 스마트 포인터 솔루션을 사용할 때는주의해야합니다. –

답변

6

사용 스마트 포인터, 그 메모리 관리를 자동으로 처리됩니다 당신은 확실 할 것이다, 그래서 당신은 할 것 :

  1. 없음 허상 포인터를;
  2. 메모리 누수가 없습니다. (당신이 C++ (11)와 함께 작동하지 않는 경우 또는 std::tr1::shared_ptr<> 또는 boost::shared_ptr<>) 올바른 선택이 경우

, 나 std::shared_ptr<>에 보인다,

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

는 또한 통지 핸들러 기능이 MyObj*의 원시 포인터 대신 std::shared_ptr<MyObj>을 받아 들여야하지만 std::shared_ptroperator ->의 오버로드를 제공하므로 해당 처리기 내의 코드는 변경하지 않아도됩니다.

일반적으로 new의 사용은 C++ 11에서 권장하지 않으며 가능하면 std::make_shared<>을 사용하여 shared_ptr을 생성해야합니다. 따라서 대신 std::shared_ptr<MyObj>을 반환하고 내부적으로 std::make_shared<MyObj>()을 사용하여 개체를 인스턴스화하게하려면 generateObj() 멤버 함수를 다시 작성해야 할 수 있습니다.

참고 :

바와 같이 코멘트에 Geier 지적은, Qt는 자신의 스마트 포인터 클래스를 사용할 수 있습니다 QSharedPointer 있습니다.

+2

Qt도 [QSharedPointer] (http://qt-project.org/doc/qt-4.8/qsharedpointer.html)와 같은 자체 공유 포인터를 가지고 있습니다. – Geier

+0

@Geier : 좋아, Qt에 익숙하지 않지만 추가 할 것입니다. 내 대답이 정보. 그걸 주셔서 감사합니다 –

+0

C에서 가져온 객체 (즉, malloc로 묶인 구조체)는 어떻게합니까? – chacham15

2

QSharedPointer을 사용할 수 있지만 다른 방법은 동적 메모리 할당을 사용하지 않는 것입니다. 코드는 그러므로 것 - 이것은 분명히 MyObj이 만들어지는 사본 발생합니다

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

. 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를 사용하는 것보다 훨씬 깔끔한 IMO입니다.

1

"newObjSignal (obj)"신호가 소비 된 슬롯에서 다른 신호를 방출 한 다음 deletelater를 호출하십시오.

Qt는에서

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