Click to See Complete Forum and Search --> : Pointer Elements & STL Containers :: STL


kuphryn
September 30th, 2002, 08:50 PM
Hi.

Do delete STL functions such as remove() and erase() calls a class destructor if the element is a pointer to an object? For example, consider a vector of pointers to ClassX objects and a list of pointers to ClassX objects..



code:--------------------------------------------------------------------------------
std::vector<ClassX *> sTextVec;

ClassX *pCX;

sTextVec.push_back(pCX);
...
// Now you need to deallocate memory from pText.
// Do functions such as remove() and erase() call ClassX
// destructor, or do you have to delete them explicitly?
--------------------------------------------------------------------------------


Thanks,
Kuphryn

Philip Nicoletti
September 30th, 2002, 09:25 PM
You need to call the destructor of ClassX yourself.

Item 7 of Scott Meyers , Effective STL :

"When using containers of new'ed pointers, remember
to delete the pointers before the container is destroyed".


You can use various smart pointers, such as Boost's shared_ptr
or the CountedPtr from the Josuttis book - they will automatically
do the delete for you.

However, you can not use the C++ auto_ptr ... (they do not
meet the requirements for elements of standard containers -
namely, after a copy or assignment of an auto_ptr, source and
sink are not equivalent.

Axter
September 30th, 2002, 09:49 PM
You can use the DeleteObject class I have listed below for deleting pointers from a container.

The example below list several methods that work in conjunction with erase and remove_if.


#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>

using namespace std;

class DeleteObject
{
public:
template<typename T>
operator()(T& ptr)
{
delete &*ptr;
ptr = NULL;
return true;
}
};

class foo
{
public:
foo(const string Name):m_Name(Name)
{
}
~foo()
{
cout << "Deleting " << m_Name << endl;
}
bool DeleteIfEq(const std::string &TestStr) const {return (TestStr == m_Name);}
typedef bool (TestFuncName)(const std::string &);
typedef int fooint;
string m_Name;
};


template<typename TestObj>
class DeleteOnMemberFunc_DeleteIfEq
{
public:
DeleteOnMemberFunc_DeleteIfEq(const TestObj& testobj) : m_testobj(testobj){}
template<typename T>
bool operator()(T& ptr)
{
if (ptr->DeleteIfEq(m_testobj))
{
delete &*ptr;
ptr = NULL;
return true;
}
return false;
}
const TestObj& m_testobj;
};


template<typename T>
bool DeleteAndNullifyIterator(T *& pObj)
{
delete pObj;
pObj = NULL;
return true;
}

bool TestFoo(foo *&MyFoo)
{
if (MyFoo->m_Name == "Deleteme")
{
return DeleteAndNullifyIterator(MyFoo);
}
return false;
}

class comp
{
public:
comp(string& _t): t(_t) {}

template<class T>
bool operator()(T& pt)
{
if(pt->m_Name == t)
{
delete pt; return true;
}
return false;
}

public:
string &t;
};

int main(int argc, char* argv[])
{
const char Items[][32] = {"One", "RemoveMe", "Deleteme", "RemoveMe", "Two", "Deleteme", "Three", "Deleteme", "Four", "RemoveMe"};
vector<foo*> Foos;
for( int i = 0;i < sizeof(Items)/32;i++)
{
Foos.push_back(new foo(Items[i]));
}
vector<foo*>::value_type x = new foo("Foo");
Foos.push_back(x);
cout << Foos.size() << endl;

Foos.erase(remove_if(Foos.begin(), Foos.end(),comp(string("Deleteme"))), Foos.end());
cout << Foos.size() << endl;

Foos.erase(remove_if(Foos.begin(), Foos.end(),DeleteOnMemberFunc_DeleteIfEq<string>("RemoveMe")), Foos.end());
cout << Foos.size() << endl;

Foos.erase(remove_if(Foos.begin(), Foos.end(),DeleteObject()), Foos.end());
cout << Foos.size() << endl;

system("pause");
return 0;
}

template<class Pred>
class DeleteObject_If
: public unary_function<Pred::first_argument_type,
Pred::result_type> {
public:
DeleteObject_If(const Pred& pr, const Pred::second_argument_type y);
result_type operator()(const argument_type& x) const;
protected:
Pred op;
Pred::second_argument_type value;
};

kuphryn
September 30th, 2002, 10:59 PM
Okay. Thanks.

I understand now from other responses and yours that STL containers do not deallocate memories that pointers point to. We have to deallocate explicitly.

Kuphryn