Understanding QTimer with Lambda and recursive function call

萝らか妹 提交于 2019-12-01 17:22:51

Given that there is no typo or some information that I am not aware of, I think the reason is that because you are trying to delete your class instance later rather than the QTimer instance allocated on the heap in the aforementioned method.

If you take a look at the the non-lambda version, that calls the deleteLater on the QTimer instance as that is the receiver in the connect call.

connect(timer, &QTimer::timeout, timer, &QTimer::deleteLater);

However, in the lambda variant, the timer instance is not captured and naturally, there would be no access to it in its current version, respectively. To make the two alternatives equivalent, this modification needs to be done to the code:

QObject::connect(timer, &QTimer::timeout, [this, timer](){
//                                               ^^^^^
    emit Log("Time out...");
    TestFunc(serverAddress, requestsFolderPath);
    timer->deleteLater();
//  ^^^^^^^
});

The default approach should be not to do manual memory management. Qt can manage timer lifetime automatically. The code becomes quite simple in Qt 5.4 and later, and can be backported for Qt 5.0-5.3:

// https://github.com/KubaO/stackoverflown/tree/master/questions/qtimer-retrofit-26713879
#include <QtCore>

struct Class : QObject {
   void TestFunc();
   void Log(const char *str) { qDebug() << str; }
};

#if QT_VERSION >= QT_VERSION_CHECK(5,4,0)
namespace compat { using QT_PREPEND_NAMESPACE(QTimer); }
#else
QT_BEGIN_NAMESPACE
Q_CORE_EXPORT void qDeleteInEventHandler(QObject *o);
QT_END_NAMESPACE
namespace compat {
using QT_PREPEND_NAMESPACE(qDeleteInEventHandler);
template <class Fun> struct SingleShotHelper : QObject, Fun {
   QBasicTimer timer;
   template <class F> SingleShotHelper(int msec, QObject *context, F &&fun) :
      QObject(context ? context : QAbstractEventDispatcher::instance()),
      Fun(std::forward<F>(fun)) {
      timer.start(msec, this);
      if (!context)
         connect(qApp, &QCoreApplication::aboutToQuit, this, &QObject::deleteLater);
   }
   void timerEvent(QTimerEvent *ev) override {
      if (ev->timerId() != timer.timerId()) return;
      timer.stop();
      (*this)();
      qDeleteInEventHandler(this);
   }
};
using Q_QTimer = QT_PREPEND_NAMESPACE(QTimer);
class QTimer : public Q_QTimer {
   Q_OBJECT
public:
   QTimer(QObject *parent = {}) : Q_QTimer(parent) {} // C++17: using Q_QTimer::Q_QTimer;
   template <class Fun>
   inline static void singleShot(int msec, QObject *context, Fun &&fun) {
      new SingleShotHelper<Fun>(msec, context, std::forward<Fun>(fun));
   }
}; }
#endif

void Class::TestFunc() {
   compat::QTimer::singleShot(1000, this, [this]{
      emit Log("Timeout...");
      TestFunc();
   });
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!