23
votes

As my usually used C++ compilers allow variable-length arrays (eg. arrays depending on runtime size), I wonder if there is something like std::array with variable size? Of course std::vectoris of variable size, but it allocates on heap, and reallocates on need.

I like to have a stack allocated array with size defined at runtime. Is there any std-template that may feature this? Maybe using std::vector with a fixed maximal size?

2
When using std::array, the size of the array is a template parameter, so it cannot be a runtime variable. I guess std::vector is your best bet. - Daniel Kamil Kozar
Since there's no "stack" in the language standard, it's hard to make this question precise, or make sense. - Kerrek SB
@DanielKamilKozar: Meh. It would be a pretty weird wart on the type system to make such a notion precise. You can see the efforts yourself in the revision history on Github. So far the idea is that "there isn't enough experience" with this, so it's being deferred. - Kerrek SB
The usual answer to this is to use std::vector with a custom allocator. Since you expect the data to be located "on the stack", presumably they will always be freed in reverse order they're allocated. It should be quite easy to write an extremely fast thread-local allocator given that restriction. The downside is that you will make a separate allocation up front to store the data, but this isn't all that different from what the OS does for your thread's stack - on a modern OS your block is virtual-only until used, just like the stack. But it won't benefit from the stack being hot in cache. - Steve Jessop
@KerrekSB: What do you mean, there's no "stack"? Automatic storage behaves just like a stack, and the language spec sometimes refers to it as a stack (e.g. "stack unwinding" when an exception is thrown), so why not call it a stack? - Mike Seymour

2 Answers

18
votes

There are two proposals currently being worked on to bring run-time fixed size arrays to C++ which may be of interest to you:

  • Runtime-sized arrays with automatic storage duration. This would make runtime sized arrays a language feature (like in C11). So you could do:

      void foo(std::size_t size) {
        int arr[size];
      }
    
  • C++ Dynamic Arrays. This would bring a new container to the library, std::dynarray, which is given a fixed size at construction. It is intended to be optimized to be allocated on the stack when possible.

      void foo(std::size_t size) {
        std::dynarray<int> arr(size);
      }
    

These are both being worked on as part of an Array Extensions Technical Specification, which will be released alongside C++14.

UPDATE: std::dynarray is not implemented yet(25Aug2021).please refer to What is the status on dynarrays?

8
votes

As Daniel stated in the comment, size of the std::array is specified as a template parameter, so it cannot be set during runtime.

You can though construct std::vector by passing the minimum capacity through the constructor parameter:

#include <vector>

int main(int argc, char * argv[])
{
    std::vector<int> a;
    a.reserve(5);
    std::cout << a.capacity() << "\n";
    std::cout << a.size();

    getchar();
}

But. Still vector's contents will be stored on the heap, not on the stack. The problem is, that compiler has to know, how much space should be allocated for the function prior to its execution, so it is simply not possible to store variable-length data on the stack.