【问题标题】:How to delete object from its method? [duplicate]如何从其方法中删除对象? [复制]
【发布时间】:2014-06-13 15:46:21
【问题描述】:

我有一个类层次结构: struct Astruct B,存储在 A 的实例中。

我运行 A 的一个方法,它运行 B 的一个方法,它与下载的连接信号异步下载一些东西到 B 的插槽。

之后我不再使用 A 和 B 实例。它们保存在向量中。

我需要的是从对象 B 获取有关下载完成的信息(来自 B 的插槽运行方法 A 以通知它并将其数据保存到 A)。通知后,不再需要B的实例(它存储了很多数据,所以我需要清除它)。但是没有其他线程知道什么时候应该完成!

调用槽B的线程不能清除B对象,因为delete this的危险。即使该线程设置了一些互斥体(可以放置在 A 中),而另一个一直在等待该互斥体的线程将删除它 - 这也是危险的,因为插槽的线程可能仍在运行。

那么,如何在 B 通知槽内安全地删除 B 实例?

我尝试在这里创建代码示例(B - 下载器,A - 存储):

struct Storage
{
    Downloader *d; // createrd in ctor
    Data data; // only value, not pointer (for some reasons). 
               //The same in 'Downloader'
    int downloadedFiles; // 0 by ctor

    void run() // think, main()
    {
        d->download(); // there is an array in my program. 
                           //Here is one Downloader*, because it is example
    }

    void finishedDownload()
    {
        ++downloadedFiles;
        data = a->data;
        // delete d; // wish, it would be done like that :( 
            // But the thread will be back to a->download()
    }
}

struct Downloader
{
    Data data;
    Internet internet;
    Storage *parent;

    void download()
    {
        internet.set('http://someurl.dat');
        connect( &internet, SIGNAL(downloaded()), this, SLOT(downloaded()) );
        internet.download(&data); // async
    }

public slots :
    void downloaded()
    {
        parent->finishedDownload();
        // And there is the finish of the thread, which was created by SIGNAL of Interget,
        //but I need to delete 'Data data' from this struct.. How?
    }
};

【问题讨论】:

  • 只需在run 方法中创建下载器作为局部变量并在那里获取数据。而且这里不需要信号/槽。
  • @Lol4t0,从互联网下载是异步的,所以我需要使用插槽/信号。
  • 如果它是异步的,则摆脱线程。
  • Internet 类是什么?
  • 德米特里萨佐诺夫,我是that downloader

标签: c++ qt qt-signals


【解决方案1】:

由于标记为 qt,请使用 this->deleteLater() 而不是 delete this

【讨论】:

  • 仅此修复程序无法使用该代码
  • 为什么不呢?父 Storage 清理了 Downloader,毕竟它创建了它(请参阅缺少 ctor 的评论,逻辑上 dtor 清理 ctor 分配的资源)
  • 首先,使用Downloader和Internet从线程,而它们属于主线程的可能是UB。如果它们确实属于线程,则下载器将无法工作,因为线程中没有启动事件处理
  • @Lol4t0:就C++而言,对象不属于线程,因此不会导致UB。 Qt 确实使用其主线程进行事件处理,因此downloaded() 将在 that 线程上调用。反过来,您调用deleteLater,这将再次删除Qt 线程上的对象。我认为没有问题。
  • 对象确实属于 Qt 术语中的线程。而且我很确定 Internet 类不是线程安全的。而且您不能从随机线程调用internet.download,而只能从互联网所属的线程调用。
猜你喜欢
  • 2018-05-27
  • 2011-03-28
  • 2016-02-28
  • 2023-03-16
  • 2023-03-24
  • 2016-09-10
  • 1970-01-01
相关资源
最近更新 更多