The declaration T a[N] requires that N be a converted constant expression.
Converted constant expression is an expression implicitly converted to
prvalue of type T, where the converted expression is a core constant
expression. If the literal constant expression has class type, it is
contextually implicitly converted to the expected integral or unscoped
enumeration type with a constexpr user-defined conversion function.
An int literal such as 5 is a prvalue, so can be used in the declaration T a[5], but an lvalue, for example int n = 5 cannot be used in the declaration T a[n], unless the lvalue under-goes an implicit lvalue-to-rvalue conversion where the lvalue:
a) has integral or enumeration type, is non-volatile const, and is
initialized with a constant expression, or an array of such (including
a string literal)
b) has literal type and refers to a non-volatile object defined with constexpr or to its non-mutable subobject
c) has literal type and refers to a non-volatile temporary, initialized with a constant expression
Therefore the following are valid:
const int n = 5;
int a[n];
constexpr int n = 5;
int a[n];
elementsand it "worked" you're using a compiler that supports VLAs in C++ (such a gcc). And though it may "work", it isn't standard. The note is accurate. If you want runtime-sizing, use astd::vector<>and heap-managed data.int foo[sz];) with dynamically allocated arrays (int *foo = new foo[sz]). The former must have its size known at compile time; the latter can have its size determined at runtime.std::vector<>in C++, which is often a better alternative. (There's alsostd::array<Type, Count>which is stored likeType[Count]but has.size(), .begin(), .end()etcetera)