Ready to practice?
Sign up to access interactive coding exercises and track your progress.
Creating Arrays at Runtime
Allocate arrays on the heap when size is determined at runtime.
Dynamically allocating arrays
In addition to dynamically allocating single values, we can also dynamically allocate arrays of variables. Unlike a fixed array, where the array size must be determined at compile time, dynamically allocating an array allows us to choose an array size at runtime (meaning our size does not need to be constexpr).
In these lessons, we'll be dynamically allocating C-style arrays, which is the most common type of dynamically allocated array.
While you can dynamically allocate a std::array, you're usually better off using a non-dynamically allocated std::vector in this case.
To allocate an array dynamically, we use the array form of new and delete (often called new[] and delete[]):
int main() { std::cout << "Enter a positive integer: "; std::size_t count{}; std::cin >> count;
int* numbers{ new int[count]{} };
std::cout << "I just allocated an array of integers of size " << count << '\n';
numbers[0] = 17;
delete[] numbers;
return 0;
}
Because we are allocating an array, C++ knows that it should use the array version of new instead of the scalar version of new. Essentially, the new\[\] operator is called, even though the \[\] isn't placed next to the new keyword.
The length of dynamically allocated arrays has type `std::size_t`. If you are using a non-constexpr int, you'll need to `static_cast` to `std::size_t` since that is considered a narrowing conversion and your compiler will warn otherwise.
Note that because this memory is allocated from a different place than the memory used for fixed arrays, the size of the array can be quite large. You can run the program above and allocate an array of size 2,000,000 (or probably even 200,000,000) without issue. Try it! Because of this, programs that need to allocate a lot of memory in C++ typically do so dynamically.
## Dynamically deleting arrays
When deleting a dynamically allocated array, we have to use the array version of delete, which is delete\[\].
This tells the CPU that it needs to clean up multiple variables instead of a single variable. One of the most common mistakes that new programmers make when dealing with dynamic memory allocation is to use delete instead of delete\[\] when deleting a dynamically allocated array. Using the scalar version of delete on an array will result in undefined behavior, such as data corruption, memory leaks, crashes, or other problems.
One often asked question of array delete\[\] is, "How does array delete know how much memory to delete?" The answer is that array new\[\] keeps track of how much memory was allocated to a variable, so that array delete\[\] can delete the proper amount. Unfortunately, this size/length isn't accessible to the programmer.
## Dynamic arrays are almost identical to fixed arrays
In the C-style array decay lesson, you learned that a fixed array holds the memory address of the first array element. You also learned that a fixed array can decay into a pointer that points to the first element of the array. In this decayed form, the length of the fixed array is not available (and therefore neither is the size of the array via sizeof()), but otherwise there is little difference.
A dynamic array starts its life as a pointer that points to the first element of the array. Consequently, it has the same limitations in that it doesn't know its length or size. A dynamic array functions identically to a decayed fixed array, with the exception that the programmer is responsible for deallocating the dynamic array via the delete\[\] keyword.
## Initializing dynamically allocated arrays
If you want to initialize a dynamically allocated array to 0, the syntax is quite simple:
```cpp
int* numbers{ new int[count]{} };
Prior to C++11, there was no easy way to initialize a dynamic array to a non-zero value (initializer lists only worked for fixed arrays). This means you had to loop through the array and assign element values explicitly.
int* grades{ new int[5] };
grades[0] = 88;
grades[1] = 92;
grades[2] = 76;
grades[3] = 81;
grades[4] = 95;
Super annoying!
However, starting with C++11, it's now possible to initialize dynamic arrays using initializer lists!
int fixedGrades[5]{ 88, 92, 76, 81, 95 };
int* grades{ new int[5]{ 88, 92, 76, 81, 95 } };
auto* grades{ new int[5]{ 88, 92, 76, 81, 95 } };
Note that this syntax has no operator= between the array length and the initializer list.
For consistency, fixed arrays can also be initialized using uniform initialization:
int fixedGrades[]{ 88, 92, 76, 81, 95 };
char message[]{ "Welcome!" };
Explicitly stating the size of the array is optional.
Resizing arrays
Dynamically allocating an array allows you to set the array size at the time of allocation. However, C++ does not provide a built-in way to resize an array that has already been allocated. It is possible to work around this limitation by dynamically allocating a new array, copying the elements over, and deleting the old array. However, this is error prone, especially when the element type is a class (which have special rules governing how they are created).
Consequently, we recommend avoiding doing this yourself. Use std::vector instead.
Summary
Dynamically allocated arrays allow setting array size at runtime using new[] operator, unlike fixed arrays which require compile-time sizes. The array form of new is called even when the brackets aren't adjacent to the new keyword.
Array length type: Dynamic array lengths use std::size_t. Converting from int to std::size_t requires a static_cast to avoid narrowing conversion warnings.
Large array support: Dynamic arrays can be much larger than stack-allocated arrays because they use heap memory. Arrays of millions of elements are feasible where stack-allocated arrays would cause stack overflow.
Array form of delete: Use delete[] (not delete) to deallocate dynamic arrays. Using the wrong form causes undefined behavior including data corruption, memory leaks, and crashes.
Memory tracking: The new[] operator tracks how much memory was allocated so delete[] can free the correct amount, but this information is not accessible to programmers.
Dynamic arrays vs decayed fixed arrays: Dynamic arrays function identically to decayed fixed arrays - both are pointers to the first element without length information. The key difference is that programmers must manually deallocate dynamic arrays with delete[].
Initializing dynamic arrays:
- Zero-initialize:
int* array{ new int[count]{} } - C++11+ initializer lists:
int* array{ new int[5]{ 88, 92, 76, 81, 95 } } - Note: No
=between array length and initializer list
No built-in resizing: C++ provides no direct way to resize an already-allocated dynamic array. Manual resizing (allocate new array, copy elements, delete old array) is error-prone. Use std::vector instead for resizable arrays.
Dynamic arrays provide flexibility for runtime-sized data but require manual memory management. For most use cases, std::vector is a safer, more convenient alternative.
Creating Arrays at Runtime - Quiz
Test your understanding of the lesson.
Practice Exercises
Dynamic Array Allocation
Practice allocating and working with dynamic arrays using new[] and delete[]. Learn to manage arrays whose size is determined at runtime.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!