Динамический массив - практика
1. Процедуральный динамический массив
Заголовок раздела «1. Процедуральный динамический массив»Видео:
Распишите код для структуры данных динамического массива:
struct DynamicArray{ // ...}- Создайте factory-функцию, которая возвращает массив изначальной максимальной длины,
заданной параметром
capacity. Создайте еще одну, которая выставляет какой-нибудь дефолтныйcapacity(например 4).
void test1(){ DynamicArray arr = createDynamicArrayWithCapacity(10); assert(arr.capacity == 10);}- Он должен давать доступ к размерности буфера (
capacity), хранить текущее количество элементов (length/count).
void test2(){ DynamicArray arr = createDynamicArray(); assert(arr.length == 0); addElementToArray(&arr, 5); assert(arr.length == 1);}- При добавлении элементов в массив, удваивайте длину, если массив полный. Имеется в виду, аллоцируйте буфер двойной длины, и перекопируйте все элементы. Добавляйте элемент в текущий конец массива.
void test3(){ DynamicArray arr = createDynamicArrayWithCapacity(1); addElementToArray(&arr, 5); assert(arr.capacity == 1); addElementToArray(&arr, 10); assert(arr.capacity == 2); addElementToArray(&arr, 20); assert(arr.capacity == 4);}- Создайте функцию для доступа к элементам массива по индексу.
Выполняйте проверку длины в этой функции, используя
assert.
void test4(){ DynamicArray arr = createDynamicArray(); addElementToArray(&arr, 5); int el = getElementAtIndex(&arr, 0); assert(el == 5);}- Создайте функцию, которая возвращает текущий кусок массива как
std::span. Пусть добавление элементов в массив инвалидирует этот взятый кусок, то есть можете просто стирать эту память без лишних проверок, если надо. Инвалидация означает, что уже имеющиеся указатели на элементы из массива становятся недействительными (память на которую они указывают могла быть удалена).
void test5(){ DynamicArray arr = createDynamicArray(); addElementToArray(&arr, 5); addElementToArray(&arr, 6); addElementToArray(&arr, 7);
std::span<int> span = getCurrentSpan(&arr);
assert(span.size() == 3); assert(span[0] == 5); assert(span[1] == 6); assert(span[2] == 7);}-
Создайте функцию, которая очищает динамическую память, выделенную функциями массива. Вызывайте эту функцию когда память массива больше не нужна (
free/destroy). -
Создайте функцию
mainв которой выполняются проверки всех этих фич (в отдельных функциях или в отдельных скоупах). Сделайте функции статическими, чтобы их невозможно было привязать в другом коде. По необходимости допишите своих тестов (как минимум 1). -
Отделите код связанный со структурой в отдельный файл - сделайте динамический массив модулем.
- Объявления функций для взаимодействия со структурой и саму структуру положите в файл
dynamicArray.h. - В
main.cppвключайте файлdynamicArray.h. - В файл
dynamicArray.cppположите определения функций.Можете положить очень короткие функции в
dynamicArray.hкакinline. - Если есть вспомогательные функции, который используете в коде массива, но не в
main, сделайте ихstaticи не добавляйте их вdynamicArray.h. - Пропишите команду которой компилируйте в
.bat(или.sh) скрипт в папке с лабой.
- Объявления функций для взаимодействия со структурой и саму структуру положите в файл
2. То же самое, но RAII
Заголовок раздела «2. То же самое, но RAII»Видео:
Проделайте то же самое, но:
- Вместо factory функций, используйте дефолтный конструктор, и конструктор с параметром
capacity. - Вместо
free/destroy, определите деструктор. - Определите конструктор копирования.
- Переопределите оператор присваивания.
- Определите move конструктор.
- Переопределите оператор присваивания с rvalue reference параметром.
- Переопределите индексатор под доступ к элементу.
addElementToArrayсделайте методом и назовитеadd.- Поля сделайте
private, сменивstructнаclass. - Предоставьте возможность считывать значения полей,
определив методы
sizeиcapacity(read-only properties). - В функции
main, протестируйте все фичи, и покажите примеры использования.
Интерфейс здесь должен выйти примерно как у
std::vector.
- Какие ошибки позволяет совершить процедуральная версия по сравнению с OOP версией? (подсказка: публичные поля, создание копий).
- Какую версию проще понять / использовать? В каких ситуациях? Почему?
- Какую роль здесь играет инкапсуляция?
Итераторы (дополнительно):
- Сделайте возможной итерацию
foreach. Для этого можете либо создать свой итератор, либо использовать метод, который возвращалstd::span.