C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Standard way to delete container of pointers
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Mike Gibson
Guest





PostPosted: Wed Oct 20, 2004 4:24 pm    Post subject: Standard way to delete container of pointers Reply with quote



As is commonly done, I have created a container of pointers to objects
of class A:

std::vector<A*> my_vector;

Now, after using this vector, I need to destroy all the memory I have
allocated so I do a for_each over all the pointers and delete each
one with:

std::for_each(my_vector.begin(), my_vector.end(), ptr_fun(&::operator
delete));

This doesn't seem to actually call the destructor for A. Is there
some problem with the way that I am using the ptr_fun adaptor? The
only way that I have found to solve this problem is create a wrapper
functor that does the same thing and use that as the parameter to
for_each:

template <class T>
struct delete_ptr : std::unary_function<T*, void>
{
void operator() (T* p) const
{
delete p;
}
};

std::for_each(my_vector.begin(), my_vector.end(), delete_ptr<A>());

Is there a more standard way of doing this? Perhaps even in something
semi-standard such as Boost?

Mike Gibson

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Thomas Mang
Guest





PostPosted: Thu Oct 21, 2004 4:00 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote




"Mike Gibson" <megibson (AT) gmail (DOT) com> schrieb im Newsbeitrag
news:c71602db.0410190901.56c7106b (AT) posting (DOT) google.com...
Quote:
As is commonly done, I have created a container of pointers to objects
of class A:

std::vector<A*> my_vector;

Now, after using this vector, I need to destroy all the memory I have
allocated so I do a for_each over all the pointers and delete each
one with:

std::for_each(my_vector.begin(), my_vector.end,ptr_fun&operator
delete));

This line contains various syntax errors, but I think I can guess what
you
want to do.

It's a big No, No.
::operator delete only frees memory. It does not call any destructors.


Quote:

This doesn't seem to actually call the destructor for A. Is there
some problem with the way that I am using the ptr_fun adaptor?

You use the wrong function to be called.


The
Quote:
only way that I have found to solve this problem is create a wrapper
functor that does the same thing and use that as the parameter to
for_each:

template struct delete_ptr : std::unary_function {
void operator() (T* p) const
{
delete p;
}
};

std::for_each(my_vector.begin(), my_vector.end,delete_ptrA


More correct than your previous try, but still wrong (besides the
obvious
syntax errors).
std::vector requires its instantiation type to be copyable. At all
times.
When you call delete p, then the pointer remaining in the vector is not
copyable any more.
The solution to this problem would be to pass the pointer per reference
and
set it to 0 after the call to delete.

However, there is left the problem with exception safety. So you go on
to:

Quote:

Is there a more standard way of doing this? Perhaps even in something
semi-standard such as Boost?

Yes. It's called shared_ptr. You instantiate your container with this
smart
pointer, and not with dumb pointers.

Alternatively, you can look for libraries that contain smart containers
invented for exactly this reason (to manage pointers to heap-objects).
Google will help you.


Thomas



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Ron Natalie
Guest





PostPosted: Thu Oct 21, 2004 4:14 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote



Mike Gibson wrote:
Quote:
As is commonly done, I have created a container of pointers to objects
of class A:

std::vector<A*> my_vector;

Presumably, each element of my_vector was individually allocated with
"new A" and nobody else is using or deleting these. Frankly, the
proper way would NOT be tossing around pointers that need to be managede
seperately, but to wrap the dynamic allocation of A inside some other
class that would manage it (perhaps a boost shared_ptr).

Quote:

Now, after using this vector, I need to destroy all the memory I have
allocated so I do a for_each over all the pointers and delete each
one with:

std::for_each(my_vector.begin(), my_vector.end(), ptr_fun(&::operator
delete));

Despite it's unfortunate name, "operator delete" is NOT the
implementation
of the delete operator, it's the memory deallcoator. Not only does the
above not call the destructors, it isn't even necesarily the way to
deallocate the memory (perhaps A used some other allocation function).

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Thorsten Ottosen
Guest





PostPosted: Thu Oct 21, 2004 4:44 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote

"Mike Gibson" <megibson (AT) gmail (DOT) com> wrote

Quote:
As is commonly done, I have created a container of pointers to objects
of class A:

std::vector<A*> my_vector;

Now, after using this vector, I need to destroy all the memory I have
allocated so I do a for_each over all the pointers and delete each
one with:

My advoce is that what you're are doing is going to be considerable
harder
than you think. For example, all member functions must be made
exception-safe
to
prevent all leaks.

Quote:
Is there a more standard way of doing this? Perhaps even in something
semi-standard such as Boost?

We just had a review of my Smart Container Library...it probably does
what you
want.
You can download the review version from

http://groups.yahoo.com/group/boost/files/pointer%20container/
smart_container.zip

Feedback is welcome

br

Thorsten


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Alberto Barbati
Guest





PostPosted: Thu Oct 21, 2004 5:10 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote

Mike Gibson wrote:
Quote:
As is commonly done, I have created a container of pointers to objects
of class A:

std::vector<A*> my_vector;

Now, after using this vector, I need to destroy all the memory I have
allocated so I do a for_each over all the pointers and delete each
one with:

std::for_each(my_vector.begin(), my_vector.end(), ptr_fun(&::operator
delete));

This doesn't seem to actually call the destructor for A. Is there
some problem with the way that I am using the ptr_fun adaptor?

The behaviour you experience is correct. "operator delete" simply frees
the storage and it's not supposed to invoke the destructor. It's the
delete-expression, i.e.: "delete p", that first invokes the destructor
and subsequently calls operator delete.

Quote:
The
only way that I have found to solve this problem is create a wrapper
functor that does the same thing and use that as the parameter to
for_each:

template <class T
struct delete_ptr : std::unary_function {
void operator() (T* p) const
{
delete p;
}
};

std::for_each(my_vector.begin(), my_vector.end(), delete_ptr

That's what I would write. Some people suggested that it should be more
correct to write:

template <class T>
struct delete_ptr : std::unary_function<T*, void>
{
void operator() (T*& p) const
{
delete p;
p = 0;
}
};

That's because leaving invalid pointers into a container may trigger
undefined behaviour on certain implementations, even if the cointer is
going to be destroyed right away. Personally, I never worked on an
implementation where that would really make a difference.

Quote:

Is there a more standard way of doing this? Perhaps even in something
semi-standard such as Boost?


In Boost there is a functional boost::checked_deleter<T> that does
exactly what your delete_ptr<T> does, plus a safety-check that the type
is actually complete (deleting an incomplete type may trigger undefined
behaviour).

HTH,

Alberto

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ulrich Eckhardt
Guest





PostPosted: Thu Oct 21, 2004 5:39 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote

Mike Gibson wrote:
Quote:
As is commonly done, I have created a container of pointers to objects
of class A:

std::vector<A*> my_vector;

Don't! Use a vector of smart pointers instead.

Quote:
Now, after using this vector, I need to destroy all the memory I have
allocated so I do a for_each over all the pointers and delete each
one with:

std::for_each(my_vector.begin(), my_vector.end(), ptr_fun(&::operator
delete));

This doesn't seem to actually call the destructor for A. Is there
some problem with the way that I am using the ptr_fun adaptor?

No, the problem is that '::operator delete' is only responsible for
releasing memory, it is NOT the same as invoking delete on a pointer.

Quote:
The only way that I have found to solve this problem is create a
wrapper functor that does the same thing and use that as the parameter
to for_each:

template <class T
struct delete_ptr : std::unary_function {
void operator() (T* p) const
{
delete p;
}
};

std::for_each(my_vector.begin(), my_vector.end(), delete_ptr
Is there a more standard way of doing this?

I don't think so.

Quote:
Perhaps even in something semi-standard such as Boost?

Boost has something called checked_delete(r), which is basically the same as
your delete_ptr<> but it additionally assures that T is a complete type(you
don't want to call delete on a pointer to an incomplete type).

Uli

--
FAQ: http://parashift.com/c++-faq-lite/

/* bittersweet C++ */
default: break;

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Thu Oct 21, 2004 5:40 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote

[email]megibson (AT) gmail (DOT) com[/email] (Mike Gibson) wrote in message
news:<c71602db.0410190901.56c7106b (AT) posting (DOT) google.com>...
Quote:
As is commonly done, I have created a container of pointers to objects
of class A:

std::vector<A*> my_vector;

Now, after using this vector, I need to destroy all the memory I have
allocated so I do a for_each over all the pointers and delete each one
with:

std::for_each(my_vector.begin(), my_vector.end(), ptr_fun(&::operator
delete));

This doesn't seem to actually call the destructor for A.

Normal. You're calling the deallocation function. There is no function
for the operator delete.

Quote:
Is there some problem with the way that I am using the ptr_fun
adaptor? The only way that I have found to solve this problem is
create a wrapper functor that does the same thing and use that as the
parameter to for_each:

template <class T
struct delete_ptr : std::unary_function {
void operator() (T* p) const
{
delete p;
}
};

std::for_each(my_vector.begin(), my_vector.end(), delete_ptr
Is there a more standard way of doing this?

Only what you're doing. Except that technically, what you're doing is
undefined behavior. It's formally illegal for a container to hold a
delete pointer, so you have to do something like:

void operator()( T*& p )
{
T* tmp = NULL ;
std::swap( tmp, p ) ;
delete tmp ;
}

In practice, I wouldn't worry about it.

Quote:
Perhaps even in something semi-standard such as Boost?

Not that I know of, although there is boost::bind.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Didier Trosset
Guest





PostPosted: Thu Oct 21, 2004 7:39 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote

Mike Gibson wrote:

--- 8< ---

Quote:
template struct delete_ptr : std::unary_function {
void operator() (T* p) const
{
delete p;
}
};

std::for_each(my_vector.begin(), my_vector.end(), delete_ptr

I've been adviced a nicer version:

struct delete_ptr
{
template <class P>
void operator() (P p)
{
delete p;
}
};

std::for_each(my_vector.begin(), my_vector.end(), delete_ptr());


Note that you don't have to specify the type of the objects you want to
delete anymore.

Didier


Quote:
Is there a more standard way of doing this? Perhaps even in something
semi-standard such as Boost?

Mike Gibson

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ralf Fassel
Guest





PostPosted: Thu Oct 21, 2004 7:41 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote

* [email]megibson (AT) gmail (DOT) com[/email] (Mike Gibson)
Quote:
Now, after using this vector, I need to destroy all the memory I
have allocated

If you'd put smart pointers in the vector, the pointers would handle
the deletion for you when they're destroyed by the vectors DTOR.

Other than that, why not

while (!myvector.empty()) {
delete myvector.back();
myvector.pop_back();
}

Has the advantage of not leaving dangling pointers in the vector (ok,
the vector will cease to exist right after this, but...)

R'

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Thomas Maeder
Guest





PostPosted: Fri Oct 22, 2004 12:09 am    Post subject: Re: Standard way to delete container of pointers Reply with quote

[email]megibson (AT) gmail (DOT) com[/email] (Mike Gibson) writes:

Quote:
As is commonly done, I have created a container of pointers to objects
of class A:

std::vector<A*> my_vector;

Now, after using this vector, I need to destroy all the memory I have
allocated

Actually, you have to destruct the objects pointed to by my_vector's
elements. Deallocating the memory they occupy is only part of the story.


Quote:
so I do a for_each over all the pointers and delete each
one with:

std::for_each(my_vector.begin(), my_vector.end(), ptr_fun(&::operator
delete));

This causes ::operator delete() to invoked for each of my_vector's elements.
::operator delete() is a mere deallocation function.


Quote:
This doesn't seem to actually call the destructor for A.

This is the consequence.


Quote:
Is there some problem with the way that I am using the ptr_fun adaptor?

No. The problem is with the approach.


Quote:
The
only way that I have found to solve this problem is create a wrapper
functor that does the same thing and use that as the parameter to
for_each:

template <class T
struct delete_ptr : std::unary_function {
void operator() (T* p) const
{
delete p;
}
};

std::for_each(my_vector.begin(), my_vector.end(), delete_ptr
Is there a more standard way of doing this? Perhaps even in something
semi-standard such as Boost?

Change the value type of my_vector:

std::vector< boost::shared_ptr my_vector;


This makes my_vector's elements the true owners of "their" A object.
The A objects they point to will be reliably destructed, e.g. when
- my_vector itself is destructed
- my_vector.clear() is called
- elements are erased from my_vector

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Daniel Aarno
Guest





PostPosted: Fri Oct 22, 2004 5:42 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote

Quote:
The
only way that I have found to solve this problem is create a wrapper
functor that does the same thing and use that as the parameter to
for_each:

template <class T
struct delete_ptr : std::unary_function {
void operator() (T* p) const
{
delete p;
}
};

std::for_each(my_vector.begin(), my_vector.end(), delete_ptr

I use two extremely usefull templates for most of my memory deallocation
needs.
Firs there is the element delter which is basically the same as the above
except that it also zeros the pointer (on demand or always for debugging)
which
can be of great help because using a 0 pointer gives segfault and not strange
behaviour.

template<typename T, bool zero=false>
class ElemDeleter {
public:
void operator()(T* &o) {
delete o;
#ifdef NDEBUG
if(zero)
#endif
o = 0;
}
};

Following the same line of thought I usually also have a
delete-and-set-to-NULL
function that I use for deletion of "normal" pointers.

template<typename T>
inline void DelNZero(T* &o) { delete o; o = NULL; }

Just don't forget that if you are working with arrays you need special
functions for them to use the correct delete[] operator.

Here I also assume the compiler is smart enough to optimize the if(false) away
for template argument (since it is known at compiletime) so the zeroing in
ElemDeleter is not any overhead if you don't use it.

Anyone care to comment on this, any insight if this is good or bad practice,
any issues I havn't thought of?

/Daniel Aarno

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Catalin Pitis
Guest





PostPosted: Fri Oct 22, 2004 5:44 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote


"Didier Trosset" <didier-dot-trosset (AT) acqiris (DOT) com> wrote

Quote:
Mike Gibson wrote:

--- 8< ---

template struct delete_ptr : std::unary_function {
void operator() (T* p) const
{
delete p;
}
};

std::for_each(my_vector.begin(), my_vector.end(), delete_ptr

I've been adviced a nicer version:

struct delete_ptr
{
template <class P
void operator() (P p)
{
delete p;
}
};

std::for_each(my_vector.begin(), my_vector.end(), delete_ptr());


Note that you don't have to specify the type of the objects you want to
delete anymore.


Why not a shorter version:
template void delete_pointer( T* p)
{
delete p;
}

for_each( my_vector.begin(), my_vector.end(), delete_pointer);


Catalin



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
jnorberg@gmail.com
Guest





PostPosted: Sat Oct 23, 2004 2:24 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote

Thomas Mang wrote:
Quote:
std::vector requires its instantiation type to be copyable. At all
times.
When you call delete p, then the pointer remaining in the vector is
not
copyable any more.

Correct me if I'm wrong, but a pointer is copyable no matter what it
points to. The container never dereference the pointer.
__
Jonas Norberg


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Frank Birbacher
Guest





PostPosted: Sun Oct 24, 2004 2:47 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote

Hi!

[email]jnorberg (AT) gmail (DOT) com[/email] wrote:
Quote:
Correct me if I'm wrong, but a pointer is copyable no matter what it
points to. The container never dereference the pointer.

No, you are wrong. Copying a pointer which does not point to a
valid object and which does not point one-past-the-end of an
array invokes undefined behaviour by the standard.

Frank


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Peter Dimov
Guest





PostPosted: Sun Oct 24, 2004 2:47 pm    Post subject: Re: Standard way to delete container of pointers Reply with quote

[email]jnorberg (AT) gmail (DOT) com[/email] wrote in message news:<1098436356.256077.274750 (AT) f14g2000cwb (DOT) googlegroups.com>...
Quote:
Thomas Mang wrote:
std::vector requires its instantiation type to be copyable. At all
times.
When you call delete p, then the pointer remaining in the vector is
not
copyable any more.

Correct me if I'm wrong, but a pointer is copyable no matter what it
points to. The container never dereference the pointer.

3.7.3.2/4: "If the argument given to a deallocation function in the
standard library is a pointer that is not the null pointer value
(4.10), the deallocation function shall deallocate the storage
referenced by the pointer, rendering invalid all pointers referring to
any part of the deallocated storage. The effect of using an invalid
pointer value (including passing it to a deallocation function) is
undefined."

Whether "using" here refers to dereference or to lvalue to rvalue
conversion is an interesting, although a bit academic, question. But
see:

http://groups.google.com/groups?selm=hnsngr-ya023180000306000631030001%40news.pacbell.net

for an example of an architecture that uses (used?) the stricter
meaning.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.