【发布时间】:2012-08-12 20:59:02
【问题描述】:
我有一个 QList 变量。如何擦除从 X 索引开始的所有元素并删除所有后续 N 元素同时释放内存?
【问题讨论】:
-
您的问题中的“X”是什么?
-
X 是我的起始索引,我应该可以从 X 行开始删除 N 个元素
我有一个 QList 变量。如何擦除从 X 索引开始的所有元素并删除所有后续 N 元素同时释放内存?
【问题讨论】:
首先,您永远不应该使用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())。
【讨论】:
erase 不是这样工作的。如果你想避免 STL(我想不出你为什么要这么做,现在是 2012 年!),你可以用 for 循环替换 for_each;由于 Qt 容器也支持迭代器,因此 STL 本身并没有什么关于使用迭代器的内容。
[range_begin, range_end) 以删除元素。然后你必须循环 尾随元素 以将它们向后移动(这是erase 所做的),然后你才能截断列表。这不是低效的。它几乎是最佳的。
QList<unique_ptr<MyClass>> 会出现问题。 QList 对push_back 的实现只接受const T& 而不是T&&。