By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,261 Members | 1,325 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,261 IT Pros & Developers. It's quick & easy.

list<class A*> l;

P: n/a
pub
When creating a list:
list<class A*> l;

How to delete all the objects whose pointers are contained in "l"?

Thanks for your comments?
Jul 22 '05 #1
Share this Question
Share on Google+
17 Replies


P: n/a
* "pub" <pu*@nospam.com> schriebt:
When creating a list:
list<class A*> l;

How to delete all the objects whose pointers are contained in "l"?


First iterate through the list and delete each object.

One way to do that is to use a 'for' loop.

Then clear the list.
--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #2

P: n/a
pub
Alf P. Steinbach <al***@start.no> wrote in message
news:40*****************@news.individual.net...
* "pub" <pu*@nospam.com> schriebt:
When creating a list:
list<class A*> l;

How to delete all the objects whose pointers are contained in "l"?


First iterate through the list and delete each object.

One way to do that is to use a 'for' loop.

Then clear the list.

Thanks! "iterate through the list" and "delete" every pointer is obvious.
What do you mean by "clear the list"?
Jul 22 '05 #3

P: n/a
"pub" <pu*@nospam.com> wrote in message
news:aQFoc.49713$Ut1.1397021@bgtnsc05-
Alf P. Steinbach <al***@start.no> wrote in message

How to delete all the objects whose pointers are contained in "l"?


First iterate through the list and delete each object.

One way to do that is to use a 'for' loop.

Then clear the list.

Thanks! "iterate through the list" and "delete" every pointer is obvious.
What do you mean by "clear the list"?


Something like

list.clear();

After deleting all the elements in the list you have invalid pointers, so to
be safe and not use them by accident you should remove them. Of course, if
the list is a member of a class and you are doing the for delete each
element in a the destructor, then you don't have to call clear.

Sometimes people do

std::list<A*>().swap(list);
Jul 22 '05 #4

P: n/a
"pub" <pu*@nospam.com> wrote in message
news:wH*********************@bgtnsc05-news.ops.worldnet.att.net...
When creating a list:
list<class A*> l;

How to delete all the objects whose pointers are contained in "l"?
Given the following utility class:
struct DeleteOp {
template<typename T>
void operator()(const T* p) const { delete p; }
};

You can use on any container of pointers:
std::foreach( l.begin(), l.end(), DeleteOp() );
Thanks for your comments?

you're welcome ?? ;)

Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
Jul 22 '05 #5

P: n/a
"Alf P. Steinbach" <al***@start.no> wrote in message news:40*****************@news.individual.net...
| * "pub" <pu*@nospam.com> schriebt:
| > When creating a list:
| > list<class A*> l;
| >
| > How to delete all the objects whose pointers are contained in "l"?
|
| First iterate through the list and delete each object.
|
| One way to do that is to use a 'for' loop.
|
| Then clear the list.

This is a *very* bad idea because it is not exception safe. For now, one should
use a container of shared_ptrs like

std::list< boost::shared_ptr<T> >

br

Thorsten
Jul 22 '05 #6

P: n/a
* "Thorsten Ottosen" <ne*****@cs.auc.dk> schriebt:
"Alf P. Steinbach" <al***@start.no> wrote in message news:40*****************@news.individual.net...
| * "pub" <pu*@nospam.com> schriebt:
| > When creating a list:
| > list<class A*> l;
| >
| > How to delete all the objects whose pointers are contained in "l"?
|
| First iterate through the list and delete each object.
|
| One way to do that is to use a 'for' loop.
|
| Then clear the list.

This is a *very* bad idea because it is not exception safe.


Do elaborate.

--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #7

P: n/a
Hi Alf,

"Alf P. Steinbach" <al***@start.no> wrote in message news:40*****************@news.individual.net...
| * "Thorsten Ottosen" <ne*****@cs.auc.dk> schriebt:
| > "Alf P. Steinbach" <al***@start.no> wrote in message news:40*****************@news.individual.net...
| > | * "pub" <pu*@nospam.com> schriebt:
| > | > When creating a list:
| > | > list<class A*> l;
| > | >
| > | > How to delete all the objects whose pointers are contained in "l"?
| > |
| > | First iterate through the list and delete each object.
| > |
| > | One way to do that is to use a 'for' loop.
| > |
| > | Then clear the list.
| >
| > This is a *very* bad idea because it is not exception safe.
|
| Do elaborate.

Consider

std::list<T*> l;
l.push_back( new T );
// ... delete pointers later in a loop

this is not exception-safe since a list has no knowlegde about ownership of the stored pointers. l.push_back
can throw bad_alloc if it cannot allocate a node; in that case the stored pointer is never freed. This
problem exists for all types of insertions in standard containers.

However, in

typedef boost::shared_ptr<T> t_ptr;
std::list< t_ptr > l;
l.push_back( t_ptr( new T ) );

the shared_ptr will call delete if push_back fails.

I'm currently working for a set of wrappers for boost that let you store pointers instead of smart pointers in standard
containers and they will be reviewed in August. There are more problems
with standard containers + raw pointers than just insertion so please use shared_ptr<> for now.

HTH

Thorsten

Jul 22 '05 #8

P: n/a
* "Thorsten Ottosen" <ne*****@cs.auc.dk> schriebt:
Hi Alf,

"Alf P. Steinbach" <al***@start.no> wrote in message news:40*****************@news.individual.net...
| * "Thorsten Ottosen" <ne*****@cs.auc.dk> schriebt:
| > "Alf P. Steinbach" <al***@start.no> wrote in message news:40*****************@news.individual.net...
| > | * "pub" <pu*@nospam.com> schriebt:
| > | > When creating a list:
| > | > list<class A*> l;
| > | >
| > | > How to delete all the objects whose pointers are contained in "l"?
| > |
| > | First iterate through the list and delete each object.
| > |
| > | One way to do that is to use a 'for' loop.
| > |
| > | Then clear the list.
| >
| > This is a *very* bad idea because it is not exception safe.
|
| Do elaborate.

Consider

std::list<T*> l;
l.push_back( new T );
// ... delete pointers later in a loop

this is not exception-safe since a list has no knowlegde about ownership of the stored pointers. l.push_back
can throw bad_alloc if it cannot allocate a node; in that case the stored pointer is never freed.


Well that depends on the context (never say never! ;-)).

But in other words what you meant was exception unsafe was not the procedure
I outlined for deleting the objects, but some specific imagined procedure for
putting the pointers into the list in the first place.

Okay.

--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #9

P: n/a
| >
| > Consider
| >
| > std::list<T*> l;
| > l.push_back( new T );
| > // ... delete pointers later in a loop
| >
| > this is not exception-safe since a list has no knowlegde about ownership of the stored pointers. l.push_back
| > can throw bad_alloc if it cannot allocate a node; in that case the stored pointer is never freed.
|
| Well that depends on the context (never say never! ;-)).
|
| But in other words what you meant was exception unsafe was not the procedure
| I outlined for deleting the objects, but some specific imagined procedure for
| putting the pointers into the list in the first place.

depends on where you execute your procedure. A lot tends to think

{
list<T*> l; l.push_back( new T );
....
for( iterator i = l.begin(); i != l.end(); ++i ) delete &*i;
}

is ok when its clearly not. Even though you wrap list<T*> in a new class with the for loop in the destructor,
you're still not safe.

br

Thorsten
Jul 22 '05 #10

P: n/a
"Thorsten Ottosen" <ne*****@cs.auc.dk> wrote in message
news:40a42fdf$0$23832
A lot tends to think

{
list<T*> l; l.push_back( new T );
....
for( iterator i = l.begin(); i != l.end(); ++i ) delete &*i;
}

is ok when its clearly not. Even though you wrap list<T*> in a new class with the for loop in the destructor, you're still not safe.


How come it is not safe when you have that code in a destructor?
Jul 22 '05 #11

P: n/a
"Ivan Vecerina" <pl****************@vecerina.com> wrote in message
You can use on any container of pointers:
std::foreach( l.begin(), l.end(), DeleteOp() );


We can also use this idea to implement the copy constructor and operator=.
Jul 22 '05 #12

P: n/a
> std::list<T*> l;
l.push_back( new T );
// ... delete pointers later in a loop

this is not exception-safe since a list has no knowlegde about ownership of the stored pointers. l.push_back
can throw bad_alloc if it cannot allocate a node; in that case the stored pointer is never freed. This
problem exists for all types of insertions in standard containers.


Can't you side step this problem by doing

std::list<T*> l;
T* TempT = new T;
l.push_back(TempT);

Now if l fails to allocate memory you can in the catch block still do
delete TempT

P.s: For anyone who reads this and think ah that is easier then to get
the boost lib. The shared_ptr has a few other handy uses concerning
memory management.
Jul 22 '05 #13

P: n/a
"Siemel Naran" <Si*********@REMOVE.att.net> wrote in message news:kh*********************@bgtnsc05-news.ops.worldnet.att.net...
| "Thorsten Ottosen" <ne*****@cs.auc.dk> wrote in message
| news:40a42fdf$0$23832
|
| > A lot tends to think
| >
| > {
| > list<T*> l; l.push_back( new T );
| > ....
| > for( iterator i = l.begin(); i != l.end(); ++i ) delete &*i;
| > }
| >
| > is ok when its clearly not. Even though you wrap list<T*> in a new class
| with the for loop in the destructor,
| > you're still not safe.
|
| How come it is not safe when you have that code in a destructor?

Because every insertion can throw. Erase need to call delete too.
And what about insertion with iterators? Or an iterator range?
Some algorithms cannot be used with list<T*> because they will overwrite
pointers. You need to protect the *whole* interface---which
a fairly big tasks, so use boost::shared_ptr for now.

br

Thorsten
Jul 22 '05 #14

P: n/a
"Thorsten Ottosen" <ne*****@cs.auc.dk> wrote in message news:40a47749$0$3033
| How come it is not safe when you have that code in a destructor?

Because every insertion can throw. Erase need to call delete too.
And what about insertion with iterators? Or an iterator range?
Some algorithms cannot be used with list<T*> because they will overwrite
pointers. You need to protect the *whole* interface---which
a fairly big tasks, so use boost::shared_ptr for now.


In the copy constructor I have try/catch blocks, and the catch block deletes
the memory allocated in the try block. We need this because if the
constructor throws, the system does not call the destructor (because the
object wasn't fully constructed, so it is not safe to call the destructor).
Then we repeat this desruction code.

So it can be done without boost::shared_ptr, and maybe sometimes it may be a
good idea for performance reasons.

But in general, I'd say go with the shared_ptr.
Jul 22 '05 #15

P: n/a
* "Thorsten Ottosen" <ne*****@cs.auc.dk> schriebt:
| >
| > Consider
| >
| > std::list<T*> l;
| > l.push_back( new T );
| > // ... delete pointers later in a loop
| >
| > this is not exception-safe since a list has no knowlegde about ownership of the stored pointers. l.push_back
| > can throw bad_alloc if it cannot allocate a node; in that case the stored pointer is never freed.
|
| Well that depends on the context (never say never! ;-)).
|
| But in other words what you meant was exception unsafe was not the procedure
| I outlined for deleting the objects, but some specific imagined procedure for
| putting the pointers into the list in the first place.

depends on where you execute your procedure.
No.

A lot tends to think

{
list<T*> l; l.push_back( new T );
....
for( iterator i = l.begin(); i != l.end(); ++i ) delete &*i;
}

is ok when its clearly not.
Again it's your imagined procedure for insertion that is unsafe, namely
code that does not properly handle an exception from push_back, and that
has nothing to do with what you answered "not exception safe" to.

The deletion code I sketched or hinted at would be safe.

The code above is not an implementation of that sketch. It's meaningless
Undefined Behavior. Remove the "&" and add clearing of the list after
the loop and the deletion part will be safe under the common assumptions.

Even though you wrap list<T*> in a new class with the for loop in
the destructor, you're still not safe.


That depends very much on the programmer... ;-)

Btw., on style: don't use lowercase ell as a name, because it's so easy to
confuse with the digit one, and do use curly braces around loop bodies.

--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #16

P: n/a
"velthuijsen" <ve*********@hotmail.com> wrote in message news:e5**************************@posting.google.c om...
| > std::list<T*> l;
| > l.push_back( new T );
| > // ... delete pointers later in a loop
| >
| > this is not exception-safe since a list has no knowlegde about ownership of the stored pointers. l.push_back
| > can throw bad_alloc if it cannot allocate a node; in that case the stored pointer is never freed. This
| > problem exists for all types of insertions in standard containers.
|
| Can't you side step this problem by doing
|
| std::list<T*> l;
| T* TempT = new T;

try
{
| l.push_back(TempT);
}
catch( ... ) { delete TempT; }

| Now if l fails to allocate memory you can in the catch block still do
| delete TempT

yes, but this is an awful awful programming style. One should strive for exception neutral code. We don't
want to insert a try catch block, we want automated memory management.

br

Thorsten
Jul 22 '05 #17

P: n/a
"velthuijsen" <ve*********@hotmail.com> wrote in message
news:e5**************************@posting.google.c om...
Can't you side step this problem by doing

std::list<T*> l;
T* TempT = new T;
l.push_back(TempT);

Now if l fails to allocate memory you can in the catch block still do
delete TempT


Rather than a try-catch block, I would use either:
std::auto_ptr<T> item = new T;
l.push_back( item.get() );
item.release();

or eventually:
std::auto_ptr<T> item = new T;
l.push_back( 00 );
l.back() = item.release();

In both cases, the auto_ptr retains the ownership of the item
until a pointer is safely stored in the list. If an exception
is thrown, the allocated object will safely be disposed of.

This said, I agree that an 'ownership-safe' container wrapper
would be nice...

Regards,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form

Jul 22 '05 #18

This discussion thread is closed

Replies have been disabled for this discussion.