#ifndef DYNAMIC_ARRAY_HEADER
#define DYNAMIC_ARRAY_HEADER
* @brief A dynamic array struct that contains the size, capacity,
* and data pointer used to implement this dynamic structure.
* @tparam T the type of data to store in the dynamic array
* @field data a pointer to the data in the dynamic array on the heap
* @field size the number of elements used in the dynamic array
* @field capacity the number of elements the dynamic array can hold
* @field default_value the default value to use when getting an element
* @brief Create a new dynamic array with the indicated initial capacity.
* @param capacity its initial capacity
dynamic_array(unsigned int capacity, T default_value)
data = (T *)malloc(sizeof(T) * capacity);
this->default_value = default_value;
// For each of the new elements... call constructor
for (int i = 0; i < capacity; i++)
// Call constructor to initialise each of the 10 elements
// Make sure that data was allocated, if not set capacity to 0
this->capacity = capacity;
* @brief Free the memory allocated to the dynamic array. Once freed
* the data in the array will no longer be accessible.
// Clear to ensure we remove any data from memory before freeing it
// Call destructors on all elements
for (int i = 0; i < capacity; i++)
// Free the data and the array itself
// Ensure we don't have a dangling pointer
* @brief Resize the capacity of the dynamic array.
* If the new capacity is smaller than the current size, the size will be updated to match the new capacity.
* @param new_capacity the new capacity of the dynamic array
* @returns true if this succeeded, or false if it could not reallocate memory
bool resize(unsigned int new_capacity)
// Call destructors if we are reducing size
for(int i = capacity - 1; i >= (int)new_capacity; i--)
// Resize the data in the array
T *new_data = (T *)realloc(data, sizeof(T) * new_capacity);
// Check if the allocation failed
// We failed to allocate memory, so we can't resize the array
// Call constructors if we increased size
for(int i = capacity; i < new_capacity; i++)
// Update the array's data and capacity
// Update the size if the new capacity is smaller than the current size
* @brief Add an element to the end of the dynamic array
* @param value the value to add to the end of the dynamic array
// Check if we need to resize the array, and if we failed to resize the array
// We double the capacity and add 1 to address issues where capacity is 0 initially
if (size >= capacity && !resize(capacity * 2 + 1))
// We didn't have space, and we failed to resize the array!
// Add the value to the end of the array
* @brief read and return the value of the indicated element from the dynamic array.
* If the index is out of bounds, the function will return the indicated default value.
* @param index the index of the element to remove
* @param default_value the value to return if the index is out of bounds
T &get(unsigned int index)
* Provide array style access to the dynamic array.
* @param index the index of the element to get
* @return const T& the element at the given index
const T &operator[](unsigned int index) const
// Check if the index is out of bounds
// The index is out of bounds, so return the default value
* Provide array style access to the dynamic array.
* @param index the index of the element to get
* @return T& the element at the given index
T &operator[](unsigned int index)
// Check if the index is out of bounds
// The index is out of bounds, so return the default value
* @brief set the value of the indicated element from the dynamic array.
* If the index is out of bounds, the function will do nothing and return false.
* @param index the index of the element to change
* @param value the value to set the element to
* @returns true when the value is set, or false if this failed
bool set(unsigned int index, T value)
// Check if the index is out of bounds
// The index is out of bounds, so do nothing