Link to home
Start Free TrialLog in
Avatar of Hamlet081299
Hamlet081299

asked on

Best way to maintain a list of objects?

I'm a bit new to C++, so excuse me if this is a stupid question.

I have a class "AItem", where each AItem can contain child AItems.  I thought this should be a pretty straightforward thing to do, but clearly my understanding of C++'s pointers is letting me down.

I had thought I could just use...
    typedef std::list<AItem> AItemList;

And then define...
    AItemList children;
... in my class.

It seemed to be working, but then when I started trying to access children, I got strange results.

I reread the documentation on list::push_back and found this...
"The content of this new element is initialized to a copy of x."

Certainly not what I wanted.  I don't want it to store "a copy of x" I want it to store x!

Maybe I should just use a dynamic array?  What would you recommend?

This seems like a pretty common thing to do, having a hierarchy of object applies to all sorts of applications, so surely it should be hard!
ASKER CERTIFIED SOLUTION
Avatar of pgnatyuk
pgnatyuk
Flag of Israel image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Hamlet081299
Hamlet081299

ASKER

Thanks pgnatyuk.

I had already tried that, but that then gave me another problem when I then tried to access the items via an iterator.

            for (AItemList::iterator it = children.begin(); it != children.end(); ++it) {
                  it->foo();
            }

Which used to work, now gives me...
invalid return type 'AItem **' for overloaded 'operator ->'

I'm sure it all just comes down to my ignorance of pointers, but how do I then make the above code work?
It's almost fine. Small fix:
(*it)->Foo();

It will work.
You know that you add element in this way:
AItem* item = new AItem;
list.push_back(item);

And you need to clear the container in the end and delete all element from it. Something like:
  for (AItemList::iterator it = children.begin(); it != children.end(); ++it) {
          delete (*it);
   }
   list.clear(); //erase from the begin() to end()
Or you can use some kind of smart pointer, like std::tr1::shared_ptr and std::tr1::weak_ptr (if your compiler supports it).
So you do not need to delete any object, when you're finished with it just forget it (i.e. get it out of scope).

http://en.wikipedia.org/wiki/Smart_pointer
SOLUTION
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks everyone for the help.  Good article on smart pointers evilrix, I added 100 points so I can give you something as well.

I'm not going to use the ref counted pointers for this, because the object creation and destruction is very tightly controlled already, but it's good to know.  I considered a vector too, but generally I don't have a need to access by index, but I do need to insert, delete, and move items mid-list for which list is more efficient.

I really just need to sit down and get my head around the way C++ does pointers especially in relation to objects.  I'm coming from a Delphi background, where objects are pointers and are treated as such.  The way that C++ implicitly makes copies of objects is a new paradigm for me.