Deleting Vectors that Point to the Same Objects

M

Mike

Hello, I hope everybody had a good New Year.

I have a class that looks like the following:

class Foo {
public:
Foo();
~Foo() {} // Destructor is defined.
....
private:
std::vector<Bar*> _list1;
std::vector<Bar*> _list2;
....
};

As my program runs, _list1 and _list2 are populated as follows:
Bar* bar = new Bar();
_list1.push_back(bar);
_list2.push_back(bar);

In general, _list2 is a subset of _list1, so it isn't redundant.

My question is, what do I need to put in the destructor of Foo to
correctly delete these vectors? When Foo is deleted, I want all the
Bars contained in the two vectors to be deleted as well.

As I understand it, because I didn't initialize the vectors with the
new keyword, they are automatically deleted along with Foo (hence the
empty destructor). However, the destructor for std::vector
automatically calls the destructor of all of its elements. Let's say
_list1 is deleted first, this means _list2 is full of dangling
pointers, and deleting _list2 in the same fashion would be bad.

Thanks for your help,
Michael
 
R

Rune Allnor

Hello, I hope everybody had a good New Year.

I have a class that looks like the following:

class Foo {
public:
        Foo();
        ~Foo() {} // Destructor is defined.
...
private:
        std::vector<Bar*> _list1;
        std::vector<Bar*> _list2;
...

};

As my program runs, _list1 and _list2 are populated as follows:
Bar* bar = new Bar();
_list1.push_back(bar);
_list2.push_back(bar);

In general, _list2 is a subset of _list1, so it isn't redundant.

My question is, what do I need to put in the destructor of Foo to
correctly delete these vectors?  

I'd have used boost::shared_pointer for these things.
The object is left alone if a pointer is deleted while
remaining pointers still refer to it, and destroyed only
when the last pointer to it is deleted.

Rune
 
Z

zr

automatically calls the destructor of all of its elements.

True. But, since each of these elements is a pointer, only the pointer
will be destroyed; the pointed objects will not be destroyed.

it seems like what you want is to call delete on each of _list1's
contained pointers in Foo::~Foo().
 
R

red floyd

I'd have used boost::shared_pointer for these things.
The object is left alone if a pointer is deleted while
remaining pointers still refer to it, and destroyed only
when the last pointer to it is deleted.

I'd agree with Rune that you should use a shared_pointer, but if you
insist on naked pointers, since list2 is a subset of list 1, just
do the following in the destructor:

for (std::vector<Bar*>::iterator it = _list1.begin();
it != _list1.end();
++it)
delete *it;

The destructor will then automatically destroy the vectors.
 
J

James Kanze

I have a class that looks like the following:
class Foo {
public:
Foo();
~Foo() {} // Destructor is defined.
...
private:
std::vector<Bar*> _list1;
std::vector<Bar*> _list2;
...
};
As my program runs, _list1 and _list2 are populated as follows:
Bar* bar = new Bar();
_list1.push_back(bar);
_list2.push_back(bar);
In general, _list2 is a subset of _list1, so it isn't redundant.
My question is, what do I need to put in the destructor of Foo
to correctly delete these vectors? When Foo is deleted, I
want all the Bars contained in the two vectors to be deleted
as well.

Just a nit, but there aren't any Bar's in your vectors. Just
pointers to Bar's.
As I understand it, because I didn't initialize the vectors
with the new keyword, they are automatically deleted along
with Foo (hence the empty destructor).
However, the destructor for std::vector automatically calls
the destructor of all of its elements.

Yes. And the destructor of a pointer is a no-op.
Let's say _list1 is deleted first, this means _list2 is full
of dangling pointers, and deleting _list2 in the same fashion
would be bad.

There won't be any dangling pointers unless you create them.
There will be a memory leak, however, unless you delete
everything you've new'ed. If _list2 really is a pure subset,
you can just delete everything in _list1. Otherwise, it's more
complicated---the simplest solution is to do what others have
suggested, use boost::shared_ptr. But it's also possible to
sort the two vectors, then merge them, removing duplicates, and
delete the set resulting from the merge. (It's not as
complicated as it sounds, but it's still a lot more work than
using boost::shared_ptr.)
 
S

saurabh gupta

Even if list2 is not a pure subset of list1, you can do this.
Iterate over the list1 pointers, remove the same pointer value from
list2 if it exists and then delete the pointer. After this, delete all
the pointers left in list2.
 
J

James Kanze

[...]
Even if list2 is not a pure subset of list1, you can do this.
Iterate over the list1 pointers, remove the same pointer value from
list2 if it exists and then delete the pointer. After this, delete all
the pointers left in list2.

Yes, but that's an n^2 algorithm. Faced with this case, I'd
rather sort and merge the lists first (n lg n), then just
iterate once. But of course, it really depends on how many
elements he expects. For 10 or so, there's probably no problem
with your suggestion.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top