• 7309阅读
  • 3回复

[讨论]做了个实验,结论很令人困惑啊,QThread对象被delete之后居然还能用 [复制链接]

上一主题 下一主题
离线zooood
 
只看楼主 倒序阅读 楼主  发表于: 2012-04-22
主要干了这么件事情:
让ThreadObj继承QThread,重写了run(),在run()里调用了deleteLater()
在main()里实例化了TheadObj,同时把ThreadObj的finished()信号连接至另一个槽,这个槽会调用ThreadObj的成员
听起来有点繁琐^-^
结果显示,ThreadObj的析构函数先被调用,然后那个槽才会被调用,而且槽里调用ThreadObj成员也是正确的。
这里不是有点矛盾吗?ThreadObj都被析构了,随后对其成员的调用怎么会正确呢?

代码:
main.h
  1. #ifndef MAIN_H
  2. #define MAIN_H
  3. #include <QtCore/QObject>
  4. #include <QtCore/QThread>
  5. #include <QtCore/QDebug>
  6. #include <QEventLoop>
  7. #include <QTimer>
  8. class ThreadObj:public QThread
  9. {
  10. Q_OBJECT
  11. public:
  12.     ThreadObj(QObject *parent=0):QThread(parent) {}
  13. public slots:
  14.     void print(){ qDebug() <<"In ThreadObj::print(), current thread id is : " << currentThreadId(); }
  15. protected:
  16.     void run(){
  17.         qDebug() << "Thread is running, current thread id is : " << currentThreadId();
  18.         QEventLoop loop;
  19.         QTimer::singleShot(2000, &loop, SLOT(quit()));
  20.         loop.exec();
  21.         deleteLater();
  22.         qDebug() << "Thread is finished";
  23.     }
  24. public:
  25.     ~ThreadObj() {
  26.         qDebug() << "delete QThread obj, current thread id is " << currentThreadId();
  27.      }
  28. };
  29. class Dummy:public QObject
  30. {
  31.     Q_OBJECT
  32. public:
  33.     Dummy(QObject* parent=0):QObject(parent) {}
  34. public slots:
  35.     void slot() {
  36.         qDebug()<< "In dummy, current threaed id is : " << QThread::currentThreadId();
  37.         b->print();
  38.     }
  39. public:
  40.     void set(ThreadObj *obj){ b = obj; }
  41. private:
  42.     ThreadObj * b;
  43. };
  44. #endif // MAIN_H

main.cpp:
  1. #include <QtCore/QCoreApplication>
  2. #include "main.h"
  3. #include <QDebug>
  4. int main(int argc, char *argv[])
  5. {
  6.     QCoreApplication a(argc, argv);
  7.     qDebug()<<"main thread:"<<QThread::currentThreadId();
  8.     Dummy *dummy = new Dummy;
  9.     ThreadObj * obj = new ThreadObj;
  10.     dummy->set(obj);
  11.     QObject::connect(obj, SIGNAL(finished()), dummy, SLOT(slot()));
  12.     obj->start();
  13.     return a.exec();
  14. }

这是运行结果:
  1. main thread: 0x9b0
  2. Thread is running, current thread id is : 0x1158
  3. Thread is finished
  4. delete QThread obj, current thread id is 0x9b0
  5. In dummy, current threaed id is : 0x9b0
  6. In ThreadObj::print(), current thread id is : 0x9b0

第4行已经提示myObj的析构函数运行,所以第4行之后myObj应该被销毁
但是第6行又成功地调用了它的print()函数打印了提示信息,这是为何?

离线lejcey

只看该作者 1楼 发表于: 2012-04-23
楼主C++没学好啊,即使你删除了指针,指针“变量”当然还在,这就是为什么删除指针之后要置零避免再次引用,而且C++可以把一个指针删除不止一次,只要你喜欢!

离线zooood
只看该作者 2楼 发表于: 2012-04-23
谢谢,不过可能我没描述清楚
结果最后一行,不是打印指针中保存的地址,而是调用了指针指向的对象中的print()函数
按照道理目标对象在第4行的时候就已经释放,为何在第6行还能被调用?

离线jdwx

只看该作者 3楼 发表于: 2012-04-23
一切的问题源于目前的PC内存太多,要是DOS时代的640k绝对会死机。
发帖时要说明:操作系统、Qt版本、编译器,这样能更快的得到回复。
快速回复
限100 字节
 
上一个 下一个