Еще одна вещь, которую следует рассмотреть, - это безопасность исключений: что произойдет, если выделение памяти или копирование объекта не удастся?В этом случае вы должны постараться, чтобы ваш класс вел себя как можно лучше.Рассмотрим следующие гарантии:
- Нет гарантии: если что-то пойдет не так, объект может оказаться в недопустимом состоянии
- Слабая гарантия: если что-то пойдет не так, объект находится в неопределенном состоянии, но действительный, состояние
- Сильная гарантия: если что-то идет не так, объект остается неизменным
- Гарантия «без броска»: ничто не может пойти не так.
Вы не можете достичь последнего здесь, так как у вас нет контроля над распределителем памяти или копируемыми объектами.Однако «сильная» гарантия возможна с использованием двухэтапного подхода: выполнять работу, которая может провалиться «на стороне», таким образом, чтобы это не влияло на видимое состояние;как только это будет успешно выполнено, обновите постоянное состояние с помощью операций, которые не могут завершиться с ошибкой (например, обновление указателей и удаление старой памяти - если удаление дает гарантию «не выбрасывать», как обычно).
Таким образом, более безопасная версия может выглядеть примерно так:
if (new_size > capacity) {
allocate new storage, controlled by a local smart pointer
copy old values
copy new values
update state, releasing the smart pointer
delete old storage
} else {
copy new values
}
Случай "else" здесь предлагает только "слабую" гарантию: если какой-либо объект не удается скопировать, то некоторые, но не все,из новых данных, возможно, были скопированы.Улучшение этого будет стоить либо с точки зрения сложности (предоставляя способ «раскручивать» изменения при сбое), либо с точки зрения скорости и памяти (используя перераспределяющуюся версию, независимо от того, достаточно ли уже памяти).