Storing polymorphic objects in STL containers

Started by
5 comments, last by chairthrower 16 years, 2 months ago
Any tips/idioms on how to store polymorphic objects in STL containers in C++? Example:

class B { ... };
class C : public B { ... };
class D : public B { ... };
In this scenario, I would like to make a vector containing a mix of B, C and D objects. If I make a
vector<B> 
, all objects would be of static type B so it wouldn't work, right? And if I make a
vector<B*>
, I need extra outside code for handling memory allocation/deallocation of B, C, and D objects, which ruins the whole idea of abstract data structures that encapsulate everything, unless I write a very complex wrapper or inherited version of vector. Any ideas/standard ways for dealing with this kind of problem in an elegant, encapsulated way?
Advertisement
In general, T* should be replaced by some_smart_pointer_implementation<T>. boost::shared_ptr is the most well known/useful.
Ok, thanks! Thinking about it again, I realize that the problem couldn't really have been solved in an easy general encapsulated way, since because I have multiple class types, I would need different allocators for each class to get any more effective than a series of heap allocations. So, shared_pointer can improve the safety problems with the pointer, but if I want more efficient allocation too, perhaps it's time for me to write a templated "slab allocator" class?
Make it work, make it maintainable, make it flexible, make it fast.

If the first three are done, then sure some sort of custom allocator might be prudent depending on your situation; otherwise it's fairly easy enough to drop in later once you get everything else working and see that the allocations are a performance problem.
Quote:Original post by all_names_taken
Ok, thanks! Thinking about it again, I realize that the problem couldn't really have been solved in an easy general encapsulated way, since because I have multiple class types, I would need different allocators for each class to get any more effective than a series of heap allocations. So, shared_pointer can improve the safety problems with the pointer, but if I want more efficient allocation too, perhaps it's time for me to write a templated "slab allocator" class?


Be careful not to optimize prematurely. As Donald Knuth once said "Premature optimization is the root of all evil" and by all means it really is!

That said, if you really need the extra boost in performance you might also use already written and tested libraries instead of developing your own. Boost also provides some nifty allocators (namely boost::pool_allocator and boost::fast_pool_allocator) that you might want to take a look at. Here's a link.

I quote:
Quote:
pool_allocator is a more general-purpose solution, geared towards efficiently servicing requests for any number of contiguous chunks. fast_pool_allocator is also a general-purpose solution, but is geared towards efficiently servicing requests for one chunk at a time; it will work for contiguous chunks, but not as well as pool_allocator. If you are seriously concerned about performance, use fast_pool_allocator when dealing with containers such as std::list, and use pool_allocator when dealing with containers such as std::vector.
If you need value semantics, you might be interested in this value_ptr.

No one has mentioned the boost pointer container library yet, which is explicitly designed to solve your problem.
I dont know what a 'slab allocator' is although i have written custom allocators for stl containers
when i have needed to (you really really shouldnt need to).

whats wrong with

vector< shared_ptr< Base> > ia;

this gives you a fast encapsulated vector of objects of polymorphic type. The allocator is only
allocating the shared_ptr types and not the underlying type. there are no expensive copy constructors
being used for the Base type since the instances are being managed by the shared pointer. you cannot
really get anything more optimised if by optimised you are talking about speed.


I normally define the shared pointer type within the object which i think leads to clearer syntax
ie

vector< Base::shared_ptr_type> ia;

alternatively use
vector< boost::any > ia;

if you want to stores types without a common derivation sub type.
<edit for clarity>

This topic is closed to new replies.

Advertisement