How do delete items in a vector if using remove_if and items are pointers to objects?
-
18-02-2021 - |
문제
I fear that I am running into memory leak issues by doing the following:
(Sample code)
class myItem //random container stuff mostly. All primatives.
{
int index;
char* name;
int val1;
int val2;
};
class vecList
{
vector< myitem* > *myVec;
void delete()
{
MyVec->erase(std::remove_if(myVec->begin(), MyVec->end(), IsMarkedToDelete), MyVec->end()); //leak here?
}
};
Erase doesn't free the memory if it's a pointer, right? If I wasn't using remove_if, I could call delete on the pointer before destroying it. How would I do it in this case? Smart Pointers? I'd prefer not to re-implement everything with them and I don't really want to add the boost library.
Thanks!
해결책
You could just delete the item in your IsMarkedToDelete
function when it returns true.
다른 팁
If the only pointers to the object were in the vector, then you've
leaked memory as soon as you call remove_if
. remove_if
moves the
pointers which you are keeping down, but it doesn't say anything about
the values behind the iterator it returns. Thus if you have something
like [a, b, c, d]
(where a
, b
, etc. represent different pointers),
then after e = remove_if( v.begin(), v.end(), matches(b) )
, your
vector might (and probably will) look like [a, c, d, d]
, with e
pointing to the second d
, and all trace of b
lost forever.
The obvious solution would be to use shared_ptr
in the vector
; this
would ensure that any pointer which ended up removed from the vector
would be deleted. Failing that, you can use two passes: the first would
be a for_each
with something like:
struct DeleteIfCondition
{
void operator()( ObjectType* &ptr ) const
{
if ( condition( *ptr ) ) {
ObjectType* tmp = ptr;
ptr = NULL;
delete tmp;
}
}
};
std::for_each( v.begin(), v.end(), DeleteIfCondition() );
as the functional object, followed by:
v.erase( std::remove( v.begin(), v.end(), NULL ), v.end() );
You can use remove_if
, then for_each
from the return value till the end and then erase. That would, of course, make your code a bit longer. Another possibility is to store shared_ptr
pointers, if your code agrees with that.
The above is a blunt lie, as Benjamin pointed out, so you're only left with "another possibility".