【问题标题】:Is it possible to delete a dereferenced Pointer是否可以删除取消引用的指针
【发布时间】:2023-04-24 12:31:01
【问题描述】:

我有一些遗留代码,其中一个对象被动态分配然后发出:

QList<MyClass *> *list = new QList<MyClass *>();
...
emit listReady(*row);

void OtherClass::slotList(QList<MyClass> list) {
    ...
    delete list???
}

我可以删除列表中的对象,我可以清除列表,是否可以删除我的插槽中的列表 itef?

【问题讨论】:

  • 是否应该将第一个list(指针)实际命名为row,以便稍后匹配其用法?

标签: c++ qt pointers delete-operator


【解决方案1】:

是否可以删除我的插槽中的列表 itef?

不,这是不可能的。因为您的插槽按值接受列表,这是原始 QList&lt;MyClass *&gt; *list 对象的副本。

void OtherClass::slotList(QList&lt;MyClass&gt; list)

为了能够删除list 对象,您应该更改slotList 参数以接受指向list 的指针。

【讨论】:

  • 好的意味着我可以在发出列表后删除我的列表,因为慢的会得到一个副本??
  • @wutzebaer 在这种特殊情况下 - 是的。但在另一种情况下,当列表将按值包含对象时,删除此列表会产生额外的开销(将对象复制到新列表,从旧列表中删除它们)并且通过指针将列表传递到槽中更容易。
  • @ikleschenkov Qt 容器与写时复制隐式共享。复制列表不会自动复制其所有元素。
【解决方案2】:

不是你写的那样。 list 参数是按值传递的,因此它是指针 list 指向的列表的 副本(如果您给两个变量指定不同的名称,这可能有助于澄清您的问题)。

即使您将 slotList 更改为通过引用 (slotList(QList&lt;MyClass&gt; &amp;list)) 获取其参数,将 delete &amp;list 放入内部仍然不是一个好主意。那是因为在 Qt 中,一些信号槽连接(例如排队连接或跨线程连接)并不直接对信号的参数进行操作,而是对其副本进行操作。

如果出于某种原因,您需要将列表的所有权从创建者信号传播到插槽并在那里删除它,则必须更改插槽以接受指针:

QList<MyClass *> *row = new QList<MyClass *>();
...
emit listReady(row);

void OtherClass::slotList(QList<MyClass> *list) {
    ...
    delete list;
}

然而,最重要的问题是:你为什么实际上首先动态分配QList?容器(如QList)很少需要动态分配。这对于通过隐式共享和写时复制实现的 Qt 容器来说更是如此,因此即使复制 QList 也很便​​宜(它不会复制其内容)。因此,最适合您的解决方案是让 row 成为对象而不是指针,而忘记整个 new/delete 业务。

【讨论】:

    【解决方案3】:

    不,这是不可能的,因为list 不是(相同的)指针,也不是对*list 的引用(在这种情况下你可以delete &amp;list;(是的,一个肮脏的黑客)——仅在直接连接的情况下)而是按值传递。

    为什么首先要动态分配列表?

    【讨论】: