Before I write my own I will ask all y'all.
I'm looking for a C++ class that is almost exactly like a STL vector but stores data into an array on the stack. Some kind of STL allocator class would work also, but I am trying to avoid any kind of heap, even static allocated per-thread heaps (although one of those is my second choice). The stack is just more efficient.
It needs to be almost a drop in replacement for current code that uses a vector.
For what I was about to write myself I was thinking of something like this:
char buffer[4096]; stack_vector<match_item> matches(buffer, sizeof(buffer));
Or the class could have buffer space allocated internally. Then it would look like:
stack_vector<match_item, 256> matches;
I was thinking it would throw std::bad_alloc if it runs out of space, although that should not ever happen.
Update
Using Chromium's stack_container.h works great!
The reason I hadn't thought of doing it this way myself is that I have always overlooked the allocator object parameter to the STL collection constructors. I have used the template parameter a few times to do static pools but I'd never seen code or written any that actually used the object parameter. I learned something new. Very cool!
The code is a bit messy and for some reason GCC forced me to declare the allocator as an actual item instead of constructing it into vector's allocator parameter. It went from something like this:
typedef std::pair< const char *, const char * > comp_list_item; typedef std::vector< comp_list_item > comp_list_type; comp_list_type match_list; match_list.reserve(32);
To this:
static const size_t comp_list_alloc_size = 128; typedef std::pair< const char *, const char * > comp_list_item; typedef StackAllocator< comp_list_item, comp_list_alloc_size > comp_list_alloc_type; typedef std::vector< comp_list_item, comp_list_alloc_type > comp_list_type; comp_list_alloc_type::Source match_list_buffer; comp_list_alloc_type match_list_alloc( &match_list_buffer ); comp_list_type match_list( match_list_alloc ); match_list.reserve( comp_list_alloc_size );
And I have to repeat that whenever I declare a new one. But it works just like I wanted.
I noticed that stack_container.h has a StackVector defined and I tried using it. But it doesn't inherit from vector or define the same methods so it wasn't a drop-in replacement. I didn't want to rewrite all the code using the vector so I gave up on it.
So no matter how you create a vector, its element is always allocated on the heap .
Although std::vector can be used as a dynamic array, it can also be used as a stack.
The Standard Template Library (STL) is a set of C++ template classes to provide common programming data structures and functions such as lists, stacks, arrays, etc. It is a library of container classes, algorithms, and iterators. It is a generalized library and so, its components are parameterized.
A std::vector can never be faster than an array, as it has (a pointer to the first element of) an array as one of its data members. But the difference in run-time speed is slim and absent in any non-trivial program. One reason for this myth to persist, are examples that compare raw arrays with mis-used std::vectors.
You don't have to write a completely new container class. You can stick with your STL containers, but change the second parameter of for example std::vector
to give it your custom allocator which allocates from a stack-buffer. The chromium authors wrote an allocator just for this:
https://chromium.googlesource.com/chromium/chromium/+/master/base/stack_container.h
It works by allocating a buffer where you say how big it is. You create the container and call container.reserve(buffer_size);
. If you overflow that size, the allocator will automatically get elements from the heap (since it is derived from std::allocator
, it will in that case just use the facilities of the standard allocator). I haven't tried it, but it looks like it's from google so i think it's worth a try.
Usage is like this:
StackVector<int, 128> s; s->push_back(42); // overloaded operator-> s->push_back(43); // to get the real std::vector. StackVector<int, 128>::ContainerType & v = s.container(); std::cout << v[0] << " " << v[1] << std::endl;
It seems that boost::static_vector is what you are searching. From the documentation:
static_vector is an hybrid between vector and array: like vector, it's a sequence container with contiguous storage that can change in size, along with the static allocation, low overhead, and fixed capacity of array. static_vector is based on Adam Wulkiewicz and Andrew Hundt's high-performance varray class.
The number of elements in a static_vector may vary dynamically up to a fixed capacity because elements are stored within the object itself similarly to an array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With