【问题标题】:Emitting a list of pointers in signal - how to handle delete在信号中发出指针列表 - 如何处理删除
【发布时间】:2014-05-23 09:20:38
【问题描述】:

我有以下内存管理问题 (qt5/c++)。我正在制作QListWidgetItems:

QList<QListWidgetItem*> items;

foreach(MyItem myItem in myItems)
{
    QListWidgetItem * item = new QListWidgetItem(myItem.text);
    items.append(item);
}

emit itemsReadyForList(items);

当发射的信号在某处被拾取时,项目可以被添加到QListWidget,并且一旦其析构函数或clear()被调用就会被删除。

但是,当这个信号没有被拾取时,如何防止生成的列表造成内存泄漏?

QListWidget::addItem() 需要一个堆对象,所以我不能基于堆栈创建 QListWidgetItems 列表并使用addItem(*item) 添加它们,因为一旦处理完信号并且列表超出范围,该项目就会被删除.

我考虑过使用QSharedPointer,但是当将原始指针传递给任何可以删除它的代码时,不应该使用它,QListWidget 会这样做。

那么我是否必须像这样创建自己的指针类(伪代码):

class MyPointer
{
    bool dontDelete = false;
    QListWidgetItem * item;

    QListWidgetItem * getPointerAndYieldControl()
    {
        dontDelete = true;
        return item;
    }

    ~MyPointer
    {
        if (!dontDelete)
            delete item;
    }
}

【问题讨论】:

    标签: c++ qt


    【解决方案1】:

    在列表中使用QSharedPointer,然后当列表未被拾取时,当列表的最后一个副本被销毁时,它们将被删除。

    当您需要保存它们时,您应该使用clone of QListWidgetItem 创建一个副本供您使用。请记住,不止一个插槽可以获取 QList。

    【讨论】:

      【解决方案2】:

      您可以将items 设为发出signal 的类的成员,然后在该类的析构函数中使用delete 取消分配。如果它是NULLnullptr,在已删除的对象上调用delete 不是问题。因此,如果signal 没有被slot 捕获,这些项目仍然会被删除。但是你必须确保分配NULLnullptr 如果信号被捕获在槽中,并且父QListWidget 被破坏。

      编辑

      至于你的评论,我想你的设计必须修改。要么仅在需要时创建项目,并在使用后销毁,要么将它们始终保留在父类中,在需要时使用并在父类被销毁时销毁。

      对我来说,更好的设计是将用作列表中项目文本的字符串保留为成员变量。然后在signal 中,传递这些字符串。在slot 中,将创建项目并将其添加到QListWidget,并使用小部件销毁项目。如果您再次需要它们,请再次生成它们。

      【讨论】:

      • 但这可能会过早地删除我的列表项。我认为在我目前的情况下它会起作用。我想我会这样做,但我希望得到一个顿悟的答案:)
      • @Halfgaar,我猜你可以使用shared_ptr 而不是自己写。
      • 我在写 C++98... 但是shared_ptr 有这样的功能吗?为什么QSharedPointer 没有?
      • 我通常也会在那时创建 QListWidgetItems,但我实际上正在做的是向列表添加 QListWidgetItem 的子类,并在再次检索所选项目时询问有关它的信息。而这些信息来自信号发出的地方。
      猜你喜欢
      • 2012-03-07
      • 1970-01-01
      • 2017-04-05
      • 1970-01-01
      • 1970-01-01
      • 2021-06-08
      • 2012-09-19
      • 2021-11-15
      • 1970-01-01
      相关资源
      最近更新 更多