Initializing an array with an initializer list
The element count of an array is not optional, so a declaration must state its size.
Why a Variable Count Feels Natural
Many learners arrive at arrays with a comfortable mental model. A variable holds a value, and that value can be supplied at runtime, computed from other values, or passed in as a parameter. It seems reasonable to assume the same flexibility applies to the number of slots in an array. If a program needs room for n items, why shouldn't the array simply be declared with n?
This belief is the misconception this article corrects. In C++, the element count of an array is part of its declaration, and it cannot be an arbitrary runtime value. The rule is strict, and the compiler enforces it before the program ever runs. Before reading the rule, try a prediction.
What do you think happens?
Inside a function that receives an int parameter n, is the declaration int a[n]; accepted by the compiler, or rejected?
Reveal answer
Rejected. The size n is a function parameter, so it is not a constant expression, and the compiler does not accept it as the element count.
A parameter's value is only known once the function is called, which is after compilation. The element count of an array must be fixed at compile time, so the declaration is refused. The rest of this article explains why and what to write instead.
The Size Is Part of the Declaration
The element count of an array is not optional, so a declaration must state its size. The size is written inside the brackets, as in int a[5]. The initializer list that follows the equals sign supplies values, but it does not supply the size. The list fills the slots that the size has already defined. It cannot define the size on its own. Providing values is not the same as providing a size.
A constant expression is a value that is fixed when the program is compiled, so the compiler knows the element count before the program runs. When an array's size is written, that size must be a constant expression.
A literal number such as 5 is a constant expression, because its value is fixed in the source code itself. A variable parameter such as n does not meet this requirement, because its value is only known once the function is called. This is the whole rule. Only the form of the size expression decides whether the declaration is accepted.
The compiler checks the element count when it reads the declaration. A size written as a function parameter is rejected, because the element count would not be known until runtime.
Accepted or Rejected at Compile Time
Consider two declarations that differ only in how the size is written. The first uses a parameter n, and the compiler rejects it. The second uses a literal 5, which is a constant expression, and the compiler accepts it. The diagram below traces the decision the compiler makes for any size expression.
Compile error: the size of the array is not a constant expression- The size is the variable n, whose value is known only when fill is called
- The compiler refuses the declaration before the program runs
- The size 5 is a literal, fixed when the program is compiled
- The initializer list {1, 2} fills the first two slots of the five defined by the size
Deciding whether a declaration is accepted
A function is written as void f(int n) { int a[n] = {1, 2, 3}; }. Is the declaration accepted?
- 1Find the size expression
The size written inside the brackets is n, not a number.
- 2Ask whether the size is fixed at compile time
n is a function parameter. Its value is only known once f is called, so it is not a constant expression.
- 3Apply the rule
The element count must be a constant expression, so the declaration is rejected. The initializer list {1, 2, 3} does not change this, because the list cannot supply the size.
- 4Correct the declaration
If the count is truly fixed, write a literal such as 3, giving int a[3] = {1, 2, 3};. If the count must vary, a vector is the appropriate tool, as discussed later.
Rejected. The size n is not a constant expression, so the element count is not fixed at compile time.
Tracing Which Slots Receive Values
Once the size is fixed, the initializer list fills positions from the start of the array. Take int a[5] = {1, 2};. The size defines five slots, indexed 0 through 4. The list supplies two values, so they go to the first two positions. The remaining positions are not left without values: in C++ they are value-initialized, which for an int means they are set to zero.
Read the diagram from left to right. The values in the list are matched to positions in order, so the list never decides where the array begins or how long it is. The declared size decides both. If the list had supplied more values than the size allows, the declaration would not describe the array the programmer intended, so the size and the list must agree.
Reading a Declaration Piece by Piece
A declaration with an initializer list has four visible parts. The type names what each element is. The name identifies the array. The bracketed size gives the element count, and it must be a constant expression. The initializer list after the equals sign supplies the initial values. The diagram below labels each part of int a[3] = {1, 2, 3};.
The bracketed part is the one this article focuses on. When you read a declaration, look there first. If the bracket holds a literal number, or another expression whose value is fixed at compile time, the element count is settled. If the bracket holds a function parameter or another value that is only known while the program runs, the declaration is not valid for a fixed-size array.
Mistakes With Array Sizes
Common mistake Assuming the initializer list determines the size
What it looks likeint a[] is not the topic here, but consider int a[n] = {1, 2, 3}; with n as a parameterWhy it failsThe list supplies values, not a size. The size must already be stated and must be a constant expression.
Do this insteadWrite the size as a constant, such as int a[3] = {1, 2, 3};, or switch to vector if the count varies.
Common mistake Using a function parameter as the array size
What it looks likevoid fill(int n) { int a[n]; }Why it failsn is only known when the function is called, so it is not a constant expression and the compiler rejects the declaration.
Do this insteadUse a literal size for an array, or use vector when the element count must come from a variable.
Common mistake Believing a fixed size means the program can never handle a changing count
Why it failsThe rule does not forbid counts that change. It means array is the wrong tool for that job.
Do this insteadWhen the element count needs to be a variable, use vector instead of array.
Common mistake Forgetting that a list shorter than the size leaves the remaining slots without listed values
Choosing Between Array and Vector
The source gives the decision rule directly: when the element count needs to be a variable, use vector instead of array. The table below compares the two choices across the situations a learner is likely to meet. A fixed-size array fits problems where the count is known as a constant. A vector fits problems where the count can only be known while the program runs.
| Situation | Use an array | Use a vector |
|---|---|---|
| The element count is a literal fixed in the code | Fits well, such as int a[3] = {1, 2, 3}; | Works, but an array is the direct match |
| The element count comes from a function parameter | Rejected, because the size is not a constant expression | Fits, such as std::vector<int> v(n); |
| The count can only be known at runtime | Not suitable, since the size must be fixed at compile time | Appropriate, because it can be sized at runtime |
Choosing a container for a fixed or variable element count
- The vector is sized from n at runtime, which the array form could not do
- The rule that the size of an array must be a constant does not apply to a vector
Checking Your Reasoning
For each declaration, decide whether it is accepted or rejected, and give the reason in terms of the size. (a) int b[4] = {9, 8}; (b) void g(int m) { int c[m]; } (c) void h() { const int k = 6; int d[k]; }. Hint: ask whether each size is fixed when the program is compiled.
Hints
- Look at what sits inside the brackets, not at the initializer list
- A literal number is fixed at compile time. A function parameter is not
- Part (c) is harder: consider whether the value of k is fixed when the program is compiled
Key Takeaways
- The element count of an array is not optional, so a declaration must state its size.
- The size must be a constant expression, a value fixed when the program is compiled. A function parameter such as n is rejected.
- An initializer list supplies values for the slots the size defines. It cannot define the size, and any slots it does not reach are filled with zero.
- When the element count needs to be a variable, use vector instead of array.