I'm reading Stroustrup's A Tour of C++. On page 9, he states:
"The size of an array must be a constant expression."
Yet later, on pg. 16, he uses the following code sample:
void vector vector_init(Vector& v, int s) { v.elem = new double[s]; // Allocate an array of s doubles v.sz = s; }
Here s
is not a constant expression, so how is initializing v.elem
to new double[s]
legal?
It is true, in C++. What you are using is a non-standard extension provided by GCC specifically, called Variable Length Arrays.
You can declare an array without a size specifier for the leftmost dimension in multiples cases: as a global variable with extern class storage (the array is defined elsewhere), as a function parameter: int main(int argc, char *argv[]) . In this case the size specified for the leftmost dimension is ignored anyway.
Answer: No. It is not possible to declare an array without specifying the size. If at all you want to do that, then you can use ArrayList which is dynamic in nature.
Variable length arrays are also known as runtime sized or variable sized arrays. The size of such arrays is defined at run-time. Variably modified types include variable length arrays and pointers to variable length arrays. Variably changed types must be declared at either block scope or function prototype scope.
There is a differentiation between allocated arrays (i.e. those created with a new[]
expression, like new double[s]
), whose lifetimes must be managed by the code (via delete[]
) and declared arrays, whose lifetimes are managed by their scope alone:
int* p = new int[s]; // allocated array, p has type int* int q[10]; // declared array, q has type int[10] std::vector<int> u; // has member allocated array std::array<int, 5> v; // has member declared array
The differentiation is not based on stack/heap. A declared array can be heap allocated (e.g. new array<int,5>
) or not on the stack (e.g. static double x[100];
)
With an allocated array, the size does not have to be a constant expression. The size will simply be encoded into the block of memory yielded by the allocator somehow (for instance the four leading bytes before the actual data starts) so that the corresponding delete[]
knows how many elements to delete.
With a declared array (or non-allocated array, no new
/malloc
/etc.), the size must† be coded into the type, so that the destructor knows what to do. The only allowed, standard array declaration is:
T D[constant-expression_opt];
(where D
is a declarator that could be a name or another array declaration, etc.) Declared arrays are not limited to the stack. Note that, for added confusion, the constant-expression is optional.
Arrays offer many sources of confusion in C++. Allocated and declared arrays have different size rules, different management practices, but you can assign a T*
to either and they're equivalently indexed. An allocated array is a pointer (that's all you get), but a declared array decays to a pointer (but is an array!).
†Note that there is a concept of a Variable Length Array (VLA). gcc, for instance, supports them as an extension, but they are non-standard C++. It gets periodically proposed though, and you can see this question for more information about them.
When creating an array whose memory is managed by compiler, its size must be (compile time) constant. For ex:
int a[5]; const int sz = 7; int b[sz] = {0};
(Some languages for ex: C (C99 onwards) support dynamic array size)
If you want a dynamically sized array (Example snippet given by you), you need to allocate memory for it by yourself you'll also need to free it with delete
when you're done. Size of such arrays can be non-const also. Moreover you need to manage the memory by yourself, allocation may fail and operators (for example sizeof
) would operate on the pointer rather than array.
In modern C++ (C++11 onwards), even stl container std::array
must have a constant size.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With