[C++] Is it good Practice to store Pointers in STL Containers?

Started by
8 comments, last by iMalc 14 years, 1 month ago
Whenever I store Objects themselves in a Vector for example, I always run into trouble due to the Fact that these Objects are usually Complex and allocate Memory internally. So copying them means solving Issues like who owns the Memory. Sometimes the Initialization of these Objects is so Complex that they were not created with the Intention of being copied anyway. So I thought why would I ever want to store Objects rather than Pointers? What is the advantage of Storing the Object itself in a Container? Is it only because when the Container is destroyed the Object is deleted? Containers usually live through all the Program execution. So I don't think that is a good Reason.
Advertisement
I use containers of objects all the time, and I recommend them. If your objects have sensible copy semantics (and they should), containers of objects work just fine. You get a clean syntax and nice automatic destruction.

Storing pointers also require paying an extra indirection to access the elements in your container, plus it might have worse cache coherency (e.g., in the case of std::vector).

I don't know why you think containers usually live through all the program execution. Perhaps that's the case in the programs you've written, but I certainly use containers locally very often.

The most common reason to want to use containers of pointers is to get polymorphic behavior. In that case, either use a container of shared pointers or one of boost's pointer containers.

Yes, the usual reason for the advise against using containers of (raw) pointers is because pointers don't clean up after themselves like good C++ objects are expected to. Some other options are containers of shared_ptr and boost pointer containers.

That being said, the advise is a general guideline, not an absolute. Containers of raw pointers work just fine and there are times when it can be reasonable to use them.
-Mike
Generally store objects, not pointers.

Storing the objects directly is generally more cache friendly, especially on containers that operate on contiguous blocks. Storing objects avoids many ownership and lifetime issues. The optimizer is often able to improve the code a little better, especially on the std::vector container.

But...

Storing pointers is sometimes needed. Consider cases of storing pointers to a base class, storing pointers to objects that you don't maintain, such as those received from external libraries, and pointers to objects that you must reference more than once.

When I need store pointers in containers, I tend to use the boost ptr_container library, as it takes care of the memory management in a more efficient way than making something like vector<shared_ptr<x> >.

I agree with the previous comments that in C++, it generally makes more sense to make a container of the object rather than a container of a pointer to the object. I would consider that the default, and then if there's a reason why this isn't a good option (e.g.: expensive copy, polymorphism, etc...) then consider an alternative.
Quote:Original post by hiigara
So I thought why would I ever want to store Objects rather than Pointers?
What is the advantage of Storing the Object itself in a Container? Is it only because when the Container is destroyed the Object is deleted? Containers usually live through all the Program execution. So I don't think that is a good Reason.
You have a struct called 'point' which contains two integer members x and y. Would you really allocate these dynamically? I think you'd find that would be a fair bit slower.

Also, the kind of objects that are large that you're perhaps shying away from storing by value in a container, sometimes are reference-counted, storing their actual data on the heap. So copying them is not expensive at all. I mean you wouldn't dynamically allocate just a pointer right (Actually I've worked on code where someone did exactly that, but I fixed that absurdity[dead]), and these often aren't much more than that.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Quote:Original post by Rydinare
When I need store pointers in containers, I tend to use the boost ptr_container library, as it takes care of the memory management in a more efficient way than making something like vector<shared_ptr<x> >.


QFT.

That said, there are slightly different semantics for ptr_vector and vector<shared_ptr<x> >. ptr_vector has total ownership of the stored objects. In general, this is a good thing (i.e. responsibility of ownership is defined),but sometimes it's useful to have a vector<shared_ptr<x> > which can contain objects that are independent of the vector.
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
Quote:Original post by ChaosEngine
Quote:Original post by Rydinare
When I need store pointers in containers, I tend to use the boost ptr_container library, as it takes care of the memory management in a more efficient way than making something like vector<shared_ptr<x> >.


QFT.

That said, there are slightly different semantics for ptr_vector and vector<shared_ptr<x> >. ptr_vector has total ownership of the stored objects. In general, this is a good thing (i.e. responsibility of ownership is defined),but sometimes it's useful to have a vector<shared_ptr<x> > which can contain objects that are independent of the vector.


I imagine that this will no longer be true -- the part about being more efficient -- with the new C++ core language features coming. Without knowing in depth what the boost::ptr_vector does internally, I imagine that RVal References, along with std::make_shared, ought to make a world of difference WRT performance of containers of pointers.

throw table_exception("(? ???)? ? ???");

Quote:Original post by Ravyne
Quote:Original post by ChaosEngine
Quote:Original post by Rydinare
When I need store pointers in containers, I tend to use the boost ptr_container library, as it takes care of the memory management in a more efficient way than making something like vector<shared_ptr<x> >.


QFT.

That said, there are slightly different semantics for ptr_vector and vector<shared_ptr<x> >. ptr_vector has total ownership of the stored objects. In general, this is a good thing (i.e. responsibility of ownership is defined),but sometimes it's useful to have a vector<shared_ptr<x> > which can contain objects that are independent of the vector.


I imagine that this will no longer be true -- the part about being more efficient -- with the new C++ core language features coming. Without knowing in depth what the boost::ptr_vector does internally, I imagine that RVal References, along with std::make_shared, ought to make a world of difference WRT performance of containers of pointers.


I haven't really investigated C++1x (as I guess we have to call it now), as I was frustrated with the slow progress, so I can't really argue with you.

But at the very least wouldn't a vector<shared_ptr<x> > have the shared_ptr overhead? I'm not saying that's a game breaker, but why do that if ptr_vector does what you need without the overhead?
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
Quote:Original post by ChaosEngine
Quote:Original post by Ravyne
Quote:Original post by ChaosEngine
Quote:Original post by Rydinare
When I need store pointers in containers, I tend to use the boost ptr_container library, as it takes care of the memory management in a more efficient way than making something like vector<shared_ptr<x> >.


QFT.

That said, there are slightly different semantics for ptr_vector and vector<shared_ptr<x> >. ptr_vector has total ownership of the stored objects. In general, this is a good thing (i.e. responsibility of ownership is defined),but sometimes it's useful to have a vector<shared_ptr<x> > which can contain objects that are independent of the vector.


I imagine that this will no longer be true -- the part about being more efficient -- with the new C++ core language features coming. Without knowing in depth what the boost::ptr_vector does internally, I imagine that RVal References, along with std::make_shared, ought to make a world of difference WRT performance of containers of pointers.


I haven't really investigated C++1x (as I guess we have to call it now), as I was frustrated with the slow progress, so I can't really argue with you.

But at the very least wouldn't a vector<shared_ptr<x> > have the shared_ptr overhead? I'm not saying that's a game breaker, but why do that if ptr_vector does what you need without the overhead?
Considering internal resizing for example, I think that move constructors will eliminate the need for the incrementing and decrementing of the reference counts, but it's still got a slightly larger object to move compared to just a pointer. For other vector operations, the gains should be along the same lines. So you've both got valid points there.

ptr_vector should still be marginally faster, but that gap should close significantly I imagine.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms

This topic is closed to new replies.

Advertisement