Is there a standard C++ class for arrays with fixed run-time-determined size?
Allocate the memory using an std::unique_ptr<T[]>
like you suggested, but to use it - construct an std::span
(in C++20; gsl::span
before C++20) from the raw pointer and the number of elements, and pass the span around (by value; spans are reference-types, sort of). The span will give you all the bells and whistles of a container: size, iterators, ranged-for, the works.
#include <span>
// or:
// #include <gsl/span>
int main() {
// ... etc. ...
{
size_t size = 10e5;
auto uptr { std::make_unique<double[]>(size) };
std::span<int> my_span { uptr.get(), size };
do_stuff_with_the_doubles(my_span);
}
// ... etc. ...
}
For more information about spans, see:
What is a "span" and when should I use one?
Use std::vector
. This is the class for runtime sized array in the STL.
It let you resize it or pushing elements into it:
auto vec = std::vector<int>{};
vec.resize(10); // now vector has 10 ints 0 initialized
vec.push_back(1); // now 11 ints
Some problems stated in the comments:
vector has an excessive interface
So is std::array
. You have more than 20 function in std::array
including operators.
Just don't use what you don't need. You don't pay for the function you won't use. It won't even increase your binary size.
vector will force initialize items on resize. As far as I know, it is not allowed to use
operator[]
for indexes >= size (despite callingreserve
).
This is not how it is meant to be used. When reserving you should then resize the vector with resize
or by pushing elements into it. You say vector will force initialize elements into it, but the problem is that you cannot call operator=
on unconstructed objects, including ints.
Here's an example using reserve:
auto vec = std::vector<int>{};
vec.reserve(10); // capacity of at least 10
vec.resize(3); // Contains 3 zero initialized ints.
// If you don't want to `force` initialize elements
// you should push or emplace element into it:
vec.emplace_back(1); // no reallocation for the three operations.
vec.emplace_back(2); // no default initialize either.
vec.emplace_back(3); // ints constructed with arguments in emplace_back
Keep in mind that there is a high chance for such allocation and use case, the compiler may completely elide construction of elements in the vector. There may be no overhead in your code.
I would suggest to measure and profile if your code is subject to very precise performance specification. If you do not have such specification, most likely this is premature optimization. The cost of memory allocation completely out measure the time it takes to initialize elements one by one.
Other parts of your program may be refactored to gain much more performance than trivial initialization can offer you. In fact, getting in the way of it may hinder optimization and make your program slower.