Sign in to follow this  

std::vector containing pointers to elements of another vector

This topic is 3665 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I just want to outline what I´m about to do: I´m trying to implement a scene-graph into my engine. In order to store elements in it there has to be a common base class for all elements. Let´s assume that class is called "Entity". Now I derive several classes from that base class which describe the actual behaviour like Objects, Shaders, Terrain... etc. For instance all Objects are beeing created in a own class which is called ObjectContainer. They are all stored in a std::vector which might look something like that:
std::vector<Object> m_Objects;
Now in order to buid up the scene-graph I tried to store the pointers to the objects above into another stl-container like that:
std::vector<std::pair<HTREEITEM, AWEntity*>> SceneGraphTree;
I know this will cause real problems since referencing to vector entries by pointers is a real bad idea. Has anyone an idea how this can be done without running into memory leaks... I´ve never had a close look at smart-pointers, might these ones help me out of that? Thanks in advance. Ralph

Share this post


Link to post
Share on other sites
Quote:
Original post by Ekast
I know this will cause real problems since referencing to vector entries by pointers is a real bad idea.
Has anyone an idea how this can be done without running into memory leaks...
I´ve never had a close look at smart-pointers, might these ones help me out of that?


It's only a problem if the objects in the first vector are stored by value (and they shouldn't be if you want to leverage polymorphism). As the vector grows or is sorted, it will shuffle things around and make copies, invalidating your preexisting pointers. If the objects are allocated on the heap (i.e., with new) and you're object manager only holds pointers to begin with, then it's fine. Just make sure that when you're done with an object, you delete it to avoid leaking memory.

What I would do would be to assign every entity a unique ID, and instead of referencing them by pointer, store them in a std::map or stdext::hash_map, and look them up by ID.

So, something like this:

stdext::hash_map<ULONG, Object*> ObjectManager;
std::vector<whatever> SceneGraph; //instead of storing pointers to objects in the ObjectManager, just store the ULONG IDs.


You can also use this in conjunction with smart pointers (boost has some good smart pointers to look into) to hold pointers to objects in the object manager.

Share this post


Link to post
Share on other sites
Thanks for your reply.
I also thought of assigning an unique ID to every entity and store them in something like a map.
The only thing is it might be a bit slower than accessing the objects by simply using the stored pointer.
Nevertheless I´ll give it a try.

Thanks

Ralph

Share this post


Link to post
Share on other sites
Quote:
For instance all Objects are beeing created in a own class which is called ObjectContainer. They are all stored in a std::vector which might look something like that:

std::vector<Object> m_Objects;


Storing pointers/iterators to elements in a std::vector is a terrible idea, because when you alter the contents of that vector all your pointers/iterators will become invalidated. One solution is to use a different storage container to allocate your objects; std::list, for example, doesn't have this limitation.

Share this post


Link to post
Share on other sites
Lists really seem to have big advantages in that case but as it has to store quite a lot of objects random access seems to be a real pain.
I should probably brood over the design for one more time :-)

Ralph

Share this post


Link to post
Share on other sites
Quote:
Original post by Driv3MeFar
What I would do would be to assign every entity a unique ID, and instead of referencing them by pointer, store them in a std::map or stdext::hash_map, and look them up by ID.


What do you gain by using a unique ID if it simply maps to a unique pointer anyway? Unless you want to do something funny like change the object that an ID references or have multiple IDs reference the same object, it seems you could as easily use the pointers directly, avoiding some complexity. Is there some benefit of IDs I'm missing here?

~Andy

Share this post


Link to post
Share on other sites
Quote:
Original post by Tonin
Quote:
Original post by Driv3MeFar
What I would do would be to assign every entity a unique ID, and instead of referencing them by pointer, store them in a std::map or stdext::hash_map, and look them up by ID.


What do you gain by using a unique ID if it simply maps to a unique pointer anyway?


The ability to let the container move the object around (and thus change the value of the pointer corresponding to the ID) under the hood, as needed to manage the container (e.g. to balance - at least partially - a binary tree, as std::map normally does).

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Quote:
Original post by Tonin
Quote:
Original post by Driv3MeFar
What I would do would be to assign every entity a unique ID, and instead of referencing them by pointer, store them in a std::map or stdext::hash_map, and look them up by ID.


What do you gain by using a unique ID if it simply maps to a unique pointer anyway?


The ability to let the container move the object around (and thus change the value of the pointer corresponding to the ID) under the hood, as needed to manage the container (e.g. to balance - at least partially - a binary tree, as std::map normally does).


I think I should have quoted more of the original post:

Quote:
Original post by Driv3MeFar

What I would do would be to assign every entity a unique ID, and instead of referencing them by pointer, store them in a std::map or stdext::hash_map, and look them up by ID.

So, something like this:

stdext::hash_map<ULONG, Object*> ObjectManager;
std::vector<whatever> SceneGraph; //instead of storing pointers to objects in the ObjectManager, just store the ULONG IDs.


My point was that if your "manager" is just a std::map<ULONG, object*> it seems you could as well use a simpler container of object* since the "manager" isn't actually doing any management of the objects themselves. Of course as you pointed out, some sort of ID system would be useful for a more complex system.

~Andy

Share this post


Link to post
Share on other sites
A pointer can serve as an "ID", sure. In general, we speak of handles.

In the OP's case I'd probably want to just use boost::shared_ptr, letting the manager create the objects dynamically and hold a container of shared_ptrs, and having it return those shared_ptrs by value.

Share this post


Link to post
Share on other sites

This topic is 3665 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this