Let's say I'd like to have a std::vector of unsigned chars. It's initialized with an initializer-list (this is C++11) and will never change. I'd like to avoid any heap allocation, even at startup time, and have the whole vector live in the data segment like const strings. Is that possible? I.e:
static const vector<char> v{0x1, 0x2, 0x3, 0x0, 0x5};
(This is a somewhat academic question; I know it's not that hard to just use C arrays for this.)

- 5,873
- 1
- 36
- 61
-
10Why not use a `std::array`? – Galik Jan 31 '18 at 22:46
-
I'm have not done it myself, but I heard this could be done via a custom (or predifinded) allocator, different to the standard allocator. But I don't know if this really makes sense in your case. – Semjon Mössinger Jan 31 '18 at 22:52
-
Remember range based for loops and iterators work just fine with C style arrays too - so a constexpr char array ought to be as easy to use as an STL container. – CookiePLMonster Jan 31 '18 at 23:23
-
If you're just trying to avoid the heap, a custom allocator is an alternative. Eg, this stack-based arena allocator: https://howardhinnant.github.io/stack_alloc.html – Daniel Waechter Feb 01 '18 at 00:02
-
`std::vector` more or less *has to* use heap memory to implement the required O(1) swap with no iterator invalidations. The constructor doesn't know that the object will be `const` and thus never swapped. – Bo Persson Feb 01 '18 at 12:23
-
@Bo yes, but if you wrapped your vector in something that provided the storage, forced a reserve to request storage, and an allocator object that failed for larger storage? Actually you have just reinvented std::array. – Gem Taylor Feb 01 '18 at 18:04
3 Answers
Why not just use a std::array
for this?
static const std::array<char, 5> v{0x1, 0x2, 0x3, 0x0, 0x5};
This avoids any dynamic allocation, since std::array
uses an internal array that is most likely declared as T arr[N]
where N is the size you passed in the template (Here 5).
While you're here, you might even want to make the variable constexpr
, which, as @MSalters points out, "gives the compiler even more opportunity to eliminate the storage for v
."

- 11,357
- 8
- 43
- 88
-
3I'd even consider making it `constexpr`. That gives the compiler even more opportunity to eliminate the storage for `v`. – MSalters Jan 31 '18 at 23:10
-
Thanks -- that works. Although I wish there were an overload for `std::array` that took the size from the initializer_list. – GaryO Feb 01 '18 at 14:27
-
1@GaryO You can use [`std::experimental::make_array`](http://en.cppreference.com/w/cpp/experimental/make_array) for that; there's an example implementation at the link if your compiler lacks the `
` header. – Ray Hamel Feb 01 '18 at 15:07 -
@ArnavBorborah re: "eliminating the storage for `v`." Assuming `v` is local to a function, declaring it `static` makes this impossible. It's faster to never declare function-local `constexpr` variables `static`. Another optimization tip for immutable arrays is to use an [`initializer_list`](http://en.cppreference.com/w/cpp/utility/initializer_list) directly: `constexpr auto v = {1, 2, 3, 4, 5};` (size: `v.size()`, random access: `v.begin()[2]`). Compilers generate slightly more efficient code for `initializer_list` than C or `std::array`s, although I don't know enough to tell you why that is. – Ray Hamel Feb 01 '18 at 15:24
If a fixed-size std::array
or builtin array isn't suitable, you can define a custom allocator that uses placement new.
That's a lot of boilerplate to write, so if you can use Boost, boost::container::static_vector
is exactly what you're looking for.

- 1,289
- 6
- 16
OP further asks:
I wish there were an overload for std::array that took the size from the initializer_list
Your wish is granted by a C++17 deduction guide:
std::array v {'\x1','\x2','\x3','\x0','\x5'};
static_assert(std::is_same_v<decltype(v), std::array<char,5>>);
g++ -std=c++17
since 7.1.0
(Clang doesn't appear to accept this yet).
cppreference links: Deduction guides for std::array, Class template argument deduction
Note that the init-list now has to contain all char
values in order to deduce the array's value type. Class deduction is all or none - you can't declare array<char>
and have just size deduced.

- 97
- 5