Как распределитель работает с std::vector?

#c #c 17

#c #c 17

Вопрос:

Я просматривал документацию для vector::vector на cppreference и в качестве упражнения пытался выяснить, как я бы реализовал explicit vector( const Allocatoramp; alloc ) noexcept;

Вопрос, который я обнаружил, задавая себе, был, почему вы передаете распределитель вектору? Это имело бы смысл только в том случае, если распределитель был полиморфным. Однако, если эта группа распределителей имеет разную информацию о состоянии, т. е. имеет разные размеры, это вызывает следующие проблемы:

  1. Вы не можете просто использовать распределитель в качестве члена / базового класса, поскольку это привело бы к нарезке объекта при копировании.
  2. Если у вас его нет в качестве элемента, его нужно было бы выделить. Распределение подразумевает, что оно может вызвать исключение.

Итак, учитывая эти причины, означает ли это, что группа распределителей должна иметь состояние только в базовом классе? Есть ли что-нибудь еще, чего мне не хватает?

Ответ №1:

Если у вас его нет в качестве элемента, его нужно было бы выделить. Распределение подразумевает, что оно может вызвать исключение.

Нет, это не обязательно должно быть выделено. Чтобы создать экземпляр std::vector , его нужно только создать с помощью копирования.

Экземпляр распределителя передается как const ссылка на std::vector конструктор. std::vector Сам по себе имеет экземпляр Allocator в качестве (частного) члена класса, и он создается путем копирования из этого параметра.

Имейте в виду, что Allocator это второй (по умолчанию) std::vector параметр шаблона. Таким образом, типичная реализация объявляет Allocator себя (частным) членом std::vector самой себя, поэтому единственное распределение, которое происходит, — это выделение std::vector самой себя.

Конструктор по умолчанию std::vector default-создает свой Allocator член класса, который также noexcept является (начиная с C 17).

Итак, краткое содержание капсулы заключается в том, что класс распределителя (начиная с C 17) должен иметь noexcept конструктор копирования и noexcept конструктор по умолчанию, чтобы он соответствовал самому noexcept требованию об исключении std::vector .

Не требуется, чтобы дополнительное выделение выполнялось как часть построения экземпляра std::vector (для конструкторов, которые не инициализируют содержимое std::vector как часть его построения) — за исключением выделения std::vector самого.