In a project about a decade ago, we found that std::vector
's dynamic allocations caused a serious performance drain. In this case it was many small vectors allocated, so the quick solution was to write a vector-like class wrapping around a stack-based pre-allocated char
array used as the raw storage for its capacity. The result was a static_vector<typename T, std::size_t Max>
. Such a thing is easy enough to write if you know a few basics, and you can find quite a few such beasts on the web. In fact, boost has one, too, now.
Working on an embedded platform now, we happen to need a static_basic_string
. That would be a string that pre-allocates a fixed maximum amount of memory on the stack and uses that as its capacity.
At first I thought this should be fairly easy (it could be based it on the existing static_vector
, after all), but looking again at std::basic_string
's interface I am not so sure anymore. It is way more complex than std::vector
's interface. Especially implementing the family of find()
functions std::basic_string
comes with is more than just a tedious task.
That got me thinking again. After all, this is what allocators were created for: replace allocation based on new
and delete
with some other means. However, to say that the allocator interface is unwieldy would be an understatement. There are a few articles out there explaining it, but there is a reason I have seen so very few home-grown allocators in the last 15 years.
So here is my question:
If you had to implement a basic_string
lookalike, how would you do it?
- Write your own
static_basic_string
? - Write an allocator to pass to
std::basic_string
? - Do something I did not think of?
- Use something from boost I am not aware of?
As always, there is a rather essential restriction for us: Being on an embedded platform, we are tied to GCC 4.1.2, so we can only employ C++03, TR1, and boost 1.52.
std::basic_string
's interface) and I am more asking about how to implement it. Yes, this is fuzzy, but I do believe the question belongs here more than there. ICBWT. – Chilstd::basic_string
instance, regardless of how its content changes later? – Copusing
declarations). – Copstd::string
with large initial capacity and some restriction at the call site on maximum string size?! The cost of a single dynamic allocation is really worse than this level of complexity and the doubtlessly fragile code that follows? I guess if you're creating a metric frakton of these things but, then, try to re-use instead? More information on the use case and the original problems you encountered may help us to provide a canonical solution that isn't just NIHing. – Acetumstruct
with lots of small string members - having them near-contiguous in memory - typically on the same page(s) of cache - sounds very advantageous compared to having each stored by pointers that - even if from the same custom pool - might be impractical to avoid allocating "discontiguously" without other undesirable coordination overheads. – Restorative