// Example class
class A : public QObject
{
Q_OBJECT
void fun() {
Timer::SingleShot(10, timerSlot); //rough code
}
public slot:
void timerSlot();
}
auto a = SharedPointer<A>(new A);
a->fun();
a->reset(); // a deleted
在这种情况下删除a并触发计时器后,它会执行timerSlot()
吗?我得到了一次非常罕见的崩溃,并且不确定它是否因为这种逻辑中有些可疑。
答案 0 :(得分:8)
即使计时器触发,也不会触发插槽。 ~QObject
状态的文档:All signals to and from the object are automatically disconnected, and any pending posted events for the object are removed from the event queue.如果您使用线程,则可以同时触发A::timerSlot
并删除A
的唯一方法是。
答案 1 :(得分:2)
在删除对象的信号和插槽之前,没有义务断开它。
QObject析构函数将为您清理过时的信号槽连接,只要您:
从QObject继承
遵循这些约定可确保您的对象在删除时发出destroyed()
信号。这实际上是Qt的信号和插槽系统用来清理悬空引用的。
如果您想添加一些调试代码来跟踪对象生命周期,您可以自己收听destroyed()
信号。
(根据您使用的Qt / moc的特定版本,很可能使用插槽的非QObject代码,或者在其标头中没有Q_OBJECT的QObject派生类仍然可以编译但是导致在运行时在垃圾指针上调用的timerSlot()
方法。)
答案 2 :(得分:0)
编辑:这个答案是对原始问题的回应,该问题没有使用QObject
但是class A
作为一个独立的类继承任何内容。该问题后来被编辑,使得这个答案过时了,但是我将其留在这里,以显示如果不使用QObject
将需要什么。
唯一可以做到这一点的方法就是让对象保持活着状态,直到定时器被触发为止。例如:
class A : enable_shared_from_this<A> {
void fun() {
QTimer::singleShot(10, bind(&A::timerSlot, shared_from_this()));
}
public:
void timerSlot();
}
auto a = SharedPointer<A>(new A);
a->fun();
a->reset(); // a goes out of scope, but its referent is kept alive by the `QTimer`.
上述工作的原因是你在设置定时器时将shared_ptr捕获到class A
,并且定时器将保持在它上面(否则它不能触发)。
如果您不喜欢或无法使用最新的C ++功能或Boost:
struct Functor {
Functor(SharedPointer<A> a) : _a(a) {}
void operator() { a->timerSlot(); }
SharedPointer _a;
};
class A {
void fun(shared_ptr<A> self) {
QTimer::singleShot(10, Functor(self));
}
public:
void timerSlot();
}
auto a = SharedPointer<A>(new A);
a->fun(a);
答案 3 :(得分:0)
由于计时器超出对象范围,我得到了一次非常罕见的崩溃,我需要只触发一次。我使用的是QTimer :: singleShot,它是静态方法,不属于QTimer对象的实例,我将使用它触发信号的上下文释放它。
这当然是在QTimer
类中解决的,并且期望的行为由timer类的实例控制,非静态QTimer::singleShot属性设置为true。
// declaration
QScopedPointer<QTimer> m_timer;
protected slots:
void onTimeout();
// usage
m_timer.reset(new QTimer);
m_timer->setSingleShot(true);
QObject::connect(m_timer.data(), SIGNAL(timeout()), this, SLOT(onTimeout()));
m_timer->start(requiredTimeout);
因此,由于上下文对象释放了计时器,因此不会发生崩溃。
答案 4 :(得分:-1)
为了达到确定性,您可以自行停止计时器:
class A : public QObject {
QTimer t;
A() { connect(Signal-Slots); }
~A() { t.stop(); }
fun() { t.start(10); }
...
};