I’m using a vector to store pointers to objects. In some cases I destroy one or more of these objects (setting the vector spaces to NULL
after each delete
call), which are externally selected:
for (int i=0; i<form->SelectListBox->Items->Count; i++) {
if (form->SelectListBox->Selected[i]) {
delete items[i];
items[i]=NULL;
}
}
After that, I have erase all NULL
pointers. This is what I’m doing and it works:
ItemVector::iterator it;
while ((it=std::find(items.begin(), items.end(), (MyObjects*)NULL))!=items.end()) {
items.erase(it);
}
Is there a more idiomatic way to “sweep” a vector of pointers? [1]
[1] As you may have guessed, I’m using C++Builder (version 6) and its VCL and try to migrate from using TList
to using std::vector
as to reduce static casts (the class TList
provides a Pack
method.
2
Your algorithm is O(N²) – if you have 1000 elements in your vector and the first 100 are null, it will run the while loop 100 times, each repositioning up to 999 elements.
In implementation, you would use two iterators, one which you read from and one which you write to. If the read element is null, do not write it, otherwise write it back and increment.
The standard algorithm for doing this is called remove_if
and there’s detail discussion in this stackoverflow question.
4
You could avoid the 2nd pass by calling erase as you delete the element. You need to convert the index to an iterator and be sure you account for the fact that erasing items changes subsequent indexes
int deleted = 0;
for (int i=0; i < Count; i++) {
if (Selected[i]) {
delete items[i];
items.erase(items.begin()+i-deleted++);
}
}
5