【问题标题】:Remove elements from QList of pointers从指针的 QList 中删除元素
【发布时间】:2012-08-12 20:59:02
【问题描述】:

我有一个 QList 变量。如何擦除从 X 索引开始的所有元素并删除所有后续 N 元素同时释放内存?

【问题讨论】:

  • 您的问题中的“X”是什么?
  • X 是我的起始索引,我应该可以从 X 行开始删除 N 个元素

标签: c++ qt4 qlist


【解决方案1】:

首先,您永远不应该使用MyClass* 来“拥有”(即控制其生命周期)MyClass 的实例。因此,MyClass* 的列表也不应该“拥有”MyClass 的任何实例。因此,您永远不会将delete 运算符与这些指针中的任何一个一起使用(并且智能指针实现之外的杂散delete 几乎总是会引起一些人的注意)。

QList 实际上是针对类似用例优化的类型。 QList<MyClass> 将在内部存储MyClass* 的动态数组(如果MyClass 大于指针),因此重新排序和扩展列表可能更便宜。但是,如果您需要从列表中删除元素而不删除它们,则应使用QList<unique_ptr<MyClass>> 或类似名称。无论哪种方式,您都不必担心对象的生命周期;您只需要将它们从列表中删除即可。

既然我说过了,有一些有用的 STL 习惯用法将有助于实现您正在寻找的东西,它们也适用于(大多数)Qt 容器(编辑:修复了删除,添加了一些有用的cmets):

QList<MyClass*> myList; //TODO FIXME XXX: clarify mentioned ownership issues
assert(X + N <= myList.size());

// this is the range of objects we want to remove and delete
// (N elements, starting from index X)
auto range_begin = myList.begin() + X,
     range_end = range_begin + N;
// delete each object in range
std::for_each(range_begin, range_end, [](MyClass* ptr) { delete ptr; });
// remove them from the list
myList.erase(range_begin, range_end);

如果您要删除myList[X - 1] 之后的所有元素,那就更简单了(简而言之,将range_end 替换为myList.end())。

【讨论】:

  • 这似乎比 Blood 的答案更不容易出错,但它使用 std,我只会坚持使用 Qt。此外,Blood 解决方案只使用一个循环,而在这里我应该使用两个循环,一个用于删除对象,一个用于从列表中删除元素。但是,我更喜欢您的回复,因为您使用了迭代器。有没有办法将你的答案和 Blood 的答案混合使用迭代器但只有一个循环?
  • @Stefano:是的,它确实使用了两个循环;但是,另一个答案确实在幕后使用了 N 个循环!您还应该注意它不会循环两次在同一范围内,因为erase 不是这样工作的。如果你想避免 STL(我想不出你为什么要这么做,现在是 2012 年!),你可以用 for 循环替换 for_each;由于 Qt 容器也支持迭代器,因此 STL 本身并没有什么关于使用迭代器的内容。
  • @Stefano:此外,您要实现的目标无法避免两个循环。首先,您必须遍历 [range_begin, range_end) 以删除元素。然后你必须循环 尾随元素 以将它们向后移动(这是erase 所做的),然后你才能截断列表。这不是低效的。它几乎是最佳的。
  • 仅供参考,在不支持移动语义的 Qt 4.x 中使用 QList&lt;unique_ptr&lt;MyClass&gt;&gt; 会出现问题。 QList 对push_back 的实现只接受const T&amp; 而不是T&amp;&amp;。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-04
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多