【问题标题】:I cannot delete an item in a QList <QByteArray*>我无法删除 QList <QByteArray*> 中的项目
【发布时间】:2021-05-17 11:21:02
【问题描述】:

我正在尝试删除(释放内存)QList 中指向 QByteArrays 的指针的所有 QByteArrays。这是我的代码:

在我的 .h 文件中

        QList<QByteArray*> GroupWord;                                   //declare the QList

在我的 .cpp 文件中

        quint8 k = GroupWord.length();                                  //get the last Index
        QByteArray& ref = *GroupWord.at(k - 1);                         //get the last Index
        qDebug() << "Length before deletion: " << GroupWord.length();   //print out the length before deletion
        qDebug() << "Before deletion: " << *GroupWord.at(k - 1);        //print out before del
        GroupWord.at(k - 1)->~QByteArray();                             //destroy the entry
        qDebug() << "Length after deletion: " << GroupWord.length();   //print out the length after deletion
        *GroupWord.at(k - 1)->append('l');                              //append to the 'assumed' deleted entry
        qDeleteAll(GroupWord);                                          //qDeleteAll the QList
        qDebug() << "After deletion 1: " << ref;                        //print out the ref to entry
        qDebug() << "After deletion 2: " << *GroupWord.at(k - 1);       //print out entry
        qDebug() << "After deletion 3: " << GroupWord.at(k - 1);        //print out the pointer
        GroupWord.clear();
        qDebug() << "After deletion 4: " << ref;                        //the memory is still there after ~QByteArray() and qDeleteAll() =(((((

以下是我如何知道有问题的 QByteArray 没有被删除:

~QArrayByte();之后QList的长度还是一样的

我真的不知道这里发生了什么:(

我知道我不应该像这样声明变量,而只是将它传递给 void;当 QList 超出范围时,它将被自动删除。但是,我只是想测试一下:(

非常感谢你们,

祝你有美好的一天,:X

【问题讨论】:

  • 您的代码中有多种未定义行为的原因:1) 在已经显式调用其析构函数的对象上调用 delete 和 2) 访问 QList 元素而不首先检查其有效性索引(QList::at 不执行边界检查)。
  • @G.M.我不知道;但是我已经编辑了我的代码以显示在执行~QByteArray() 之后 QList 的长度仍然相同。我做错什么了吗? :
  • QByteArray 对象在其析构函数被调用后不存在 -- 它的生命周期已经结束。访问它使用的内存(通过GroupWord.length())是未定义的行为。
  • @G.M.我不确定我是否正确理解:QList 的 QByteArray*;我只想销毁/释放用于 GroupWord 的最后一个索引的内存,这个最后一个索引本身是一个 QByteArray 指针。并且在调用QByteArray::~QByteArray 之后,指针仍然存在,它没有设置为null,或者它应该是什么。
  • 是的,这很好,因为对象被销毁了。

标签: c++ qt memory-management qlist qbytearray


【解决方案1】:

GroupWord.at(k - 1)-&gt;~QByteArray(); 销毁对象但不释放其动态存储的内存。您从未从 QList 中删除指针。存储对象本身而不是指针会.. 实际上,QList 将存储指针并开始管理对象,如果它们是 QObjectQList 太聪明了,它本身就太聪明了,被设计为防白痴)。如果您尝试调用析构函数,这将导致 UB。

QList“知道”它的长度只是由于对其方法的调用,它会跟踪它。您所做的破坏超出了它的范围:GroupWord.at(k - 1) 是对 QList 成员的调用,-&gt;~QByteArray(); 是在 at 指针返回的对象上下文中对 QByteArray 方法的调用。

您几乎永远不会显式调用析构函数。实际需要的极少数情况是分配具有位置new 的对象,因为存储不属于它们,因此您不能调用删除。

QList 在其内部使用了一种新的放置形式,但随着 Qt 版本的不同而变化。重要的是它不是一个连续存储其元素的容器。如果您将指针存储在QList&lt;QByteArray*&gt; 中,则必须手动删除它们并在适当的情况下将delete 指向对象:当心双重删除或删除不是由new 创建的东西。如果您使用QList&lt;QByteArray&gt;QList 会自动管理它,但它总是会复制。

【讨论】:

  • 我想我有点明白你的意思了。因此,假设我将 .h 文件从 QList&lt;QByteArray*&gt; GroupWord; 更改为 QList&lt;QByteArray&gt; GroupWord;(不带星号);而且我很担心内存泄漏;我应该申请GroupWord.clear() 吗?它会照顾好一切吗?
  • @user49685 是的,它是一个智能容器,它正是文档中所写的内容。 std::vector 也是如此。您得到的缺点是这些列表正在获取副本。您的方式并没有完全错误,但是使用~QByteArray(); 是非常错误的,您实际上会导致内存泄漏,因为您无法再删除该对象。
  • 我还有一个问题,最后一段中的“但它总是会复制”是什么意思? If you use QList&lt;QByteArray&gt;, QList manages that automatically, but it would always make a copy.?非常感谢:*
  • @user49685 不知道有什么不清楚的地方。 QList&lt;QByteArray&gt; 类型名的语义假设它存储了QByteArray,对吧?然后实际上它分配指向QList 的指针,但创建一个新的QByteArray 对象来存储一个副本,即QByteArray 的一个实例。如果您复制此 QList 或将全新的 QByteArray 分配给一个元素,则 QByteArray 及其元素将发生复制分配或构造。 QList&lt;QByteArray*&gt; 只存储指针,它们可能指向非唯一的 QByteArray
  • @user49685 一般而言,通过“尝试”来尝试对 C++ 执行此操作是有问题的,因为 C++ 有许多您将看不到的细微规则并且代码将“工作”。而且你包括一个不能作为“经典”C++ 工作的生态系统。 Qt 基本上否定了一些 C++ 实践,因为大部分内部工作是隐藏的,它试图模拟 Java 行为
猜你喜欢
  • 2020-06-25
  • 1970-01-01
  • 2021-09-23
  • 1970-01-01
  • 2020-01-27
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
相关资源
最近更新 更多