У меня есть переменная QList. Как я могу стереть все элементы, начиная с индекса X, и удалить все последующие элементы N, позаботившись также об освобождении памяти?
Удалить элементы из QList указателей
Ответы (1)
Прежде всего, вы никогда не должны использовать MyClass*
для "владения" (т.е. контроля времени жизни) экземпляром MyClass
. Таким образом, список MyClass*
также не должен «владеть» какими-либо экземплярами MyClass
. Таким образом, вы никогда не будете использовать оператор delete
ни с одним из этих указателей (и случайный delete
за пределами реализации умного указателя почти всегда должен вызывать удивление).
QList
на самом деле является типом, оптимизированным для аналогичного варианта использования. QList<MyClass>
будет внутренне хранить динамический массив MyClass*
(если MyClass
больше указателя), поэтому изменение порядка и расширение списка потенциально дешевле. Однако, если вам нужно удалить элементы из списка, не удаляя их, вы должны использовать QList<unique_ptr<MyClass>>
или аналогичный. В любом случае вам не придется беспокоиться о времени жизни объектов; вам нужно только удалить их из списка.
Теперь, когда я это сказал, есть несколько полезных идиом STL, которые помогут достичь того, что вы ищете, и они также применимы к (большинству) контейнеров Qt (редактировать: исправлено удаление, добавлено несколько полезных комментариев< /эм>):
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_each
циклом for
; в использовании итераторов нет ничего общего с STL, поскольку контейнеры Qt также их поддерживают.
- person eq-; 13.08.2012
[range_begin, range_end)
, чтобы удалить элементы. Затем вам нужно пройтись по конечным элементам, чтобы переместить их назад (это то, что делает erase
), и только тогда вы можете обрезать список. Это не неэффективно; это настолько оптимально, насколько это возможно.
- person eq-; 13.08.2012
QList<unique_ptr<MyClass>>
будет проблематичным в Qt 4.x, который не поддерживает семантику перемещения. Реализация QList
push_back
принимает только const T&
, но не T&&
.
- person Bret Kuhns; 19.12.2012