Это действительно хорошее начало! Чистое и простое решение для упражнения. К сожалению, ваши инстинкты правы в том, что вы не тестировали достаточно случаев.
Одна вещь, которая бросается в глаза, это то, что вы никогда не изменяете размеры своих векторов и, следовательно, не измеряете, как большинство реализаций STL часто могут избежать копирования когда они растут в размерах. Он также никогда не возвращает память в кучу при сжатии. Вы также не говорите, компилировали ли вы с /Oz
для включения оптимизации. Но я предполагаю, что в реализации Microsoft есть небольшие накладные расходы, и это окупится в других тестах (особенно в массиве нетривиально копируемых данных, размер которых необходимо изменить, или в серии векторов, которые начинаются с больших, но может быть отфильтрован и сокращен, или хранит много данных, которые могут быть перемещены вместо копирования).
Одна ошибка, которая выскакивает из меня, это то, что вы вызываете new[]
, чтобы выделить буфер char
- который не гарантируется соответствие требованиям выравнивания T. На некоторых процессорах, которые могут обработать sh программу.
Другое - вы используете std::copy
с неинициализированной областью памяти в качестве места назначения в List::setCapacity
. Это не работает, за исключением особых случаев: std::copy
ожидает корректно инициализированный объект, который может быть назначен. Для любого типа, где присваивание является нетривиальной операцией, это завершится неудачно, когда программа попытается вызвать деструктор для данных мусора. Если это сработает, то перемещение будет неэффективно клонировать данные и уничтожить оригинал, а не использовать конструктор перемещения, если таковой существует. Алгоритм STL, который вам действительно нужен, это std::uninitialized_move
. Возможно, вы также захотите использовать calloc
/ realloc
, что позволяет изменять размеры блоков.
Ваши элементы емкости и размера должны быть size_t
, а не int
. Это не только ограничивает размер памяти меньшим, чем может реализовать большинство реализаций, но вычисление размера, превышающего INT_MAX
(т. Е. 2 ГБ или более в большинстве реализаций), приводит к неопределенному поведению.
Одна вещь List::push
имеет для этого используется семантика std::vector::emplace_back
(которую вы понимаете и используете для сравнения). Это, однако, может быть улучшено. Вы передаете item
по значению, а не по константной ссылке. Это создает ненужную копию данных. К счастью, если T
имеет конструктор перемещения, дополнительную копию можно переместить, и если item
является значением xvalue, компилятор может оптимизировать ее удаление, но было бы лучше иметь List::push(const T&)
и List::push(T&&)
. Это позволит классу pu sh xvalue вообще не делать копий.
List::get
лучше и избегает делать копии, но у него нет версии const
, поэтому const List<T>
ничего не может сделать. Он также не проверяет границы.
Рассмотрите возможность помещения кода для поиска позиции индекса в буфере в частную встроенную функцию-член, что значительно сократит объем работы, которую вам нужно будет выполнить исправьте изменения в дизайне (например, те, которые вам понадобятся для исправления ошибки выравнивания данных).