4

I'm pretty new to C++ so please bear with me: I am looking to set an array's size to the output of a function, for example:

//this is not the actual function, (go figure)
int getSizeInt(int size)
{
    return size;
}

int main()
{
    char charArray[getSizeInt(6)]; // Error: *function call must have a constant value in a constant expression*
    return 0;
}

This may not be possible, I honestly don't know. I googled the issue and have been tinkering with different ways of initializing an array, but upto to no avail.

  • Nope, array sizes must be constant expressions. If your function can be evaluated at compile time, use `constexpr`. Otherwise, the best way probably is to use `std::vector`. – eesiraed May 08 '20 at 03:04
  • Variable Length Arrays shouldn't be used https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard – fas May 08 '20 at 03:05
  • It is technically possible using C style arrays to do this however I really would not recommend it.`int *a = malloc(sizeof(int) * s)`. You'd be far better using `vector` as suggested in other answers – Jay May 08 '20 at 04:13

2 Answers2

2

Is there a possible way to set a c++ array size to the return value of a function

Yes.

The size of an array variable must be compile time constant. A function call is a constant expression if the function is constexpr and its arguments themselves are constant expressions.

Your function does not satisfy those constraints, so its return value cannot be used as the size of an array variable.

It however can be used as the size of a dynamic array. Simplest way to create a dynamic array is to use std::vector (std::string may be considered instead if your intention is to represent text):

std::vector<char> charArray(getSizeInt(6));
eerorika
  • 232,697
  • 12
  • 197
  • 326
1

Array sizes in C++ must be constant at compile-time, so the answer is sort of.

If your function is constexpr and called as part of a constant expression, then it can be used to statically set the size of the array. For example:

constexpr std::size_t square(std::size_t n) { return n * n; }

int my_array[compute_size(2)]; // array of 4 integers

However, this only works if you know all the data up-front at compile-time. If you are working with runtime values, such as things coming from files or from a user, then this will not work -- and you will have to resort to some other form of dynamic memory to handle this. In C++, generally this would be handled by a container such as a std::vector:

std::size_t compute_size() { /* some computation based on runtime */ }

// ...

auto vec = std::vector<int>{};
vec.reserve(compute_size()); // reserve the size up-front

vec.push_back( ... ); // push_back or emplace_back any data you need

If you reserve the size up front, you are able to avoid reallocation costs from push_back/emplace_back, provided you don't exceed the capacity.

Alternatively, you can initialize a vector of entries by doing either:

auto vec = std::vector<T>{};
vec.resize(N);

or

auto vec = std::vector<T>(N);

The difference here is that reserve only changes the capacity, which means you can't actually index up to N until you insert the elements -- whereas resize or vector<T>(N) will zero-initialize (fundamental types like ints) or default-construct (aggregate/class types) N instances immediately, which allows indexing.

Generally, reserve + push_back is better unless you know you want default-constructed / zero values.

Human-Compiler
  • 11,022
  • 1
  • 32
  • 59