Подтвердить что ты не робот

Почему std:: allocator строит и уничтожает функции, устаревшие в С++ 17?

Спецификация С++ 17 обесценивает членов construct и destroy объекта std::allocator. Рабочая группа предоставила обоснование для обесценивания других функций-членов здесь, под заголовком "Устаревать избыточные члены std:: allocator".

Однако они не упоминают конкретно, почему эти два члена устарели или что рекомендация заключается в замене этой функциональности. Я предполагаю, что подразумевается использование std::allocator_traits::construct вместо этого.

Я немного смущен тем, что реализация construct может быть по-прежнему необходима в некоторых случаях, хотя из-за этого комментария о std::allocator_traits::construct

Поскольку эта функция обеспечивает автоматическое возвращение назад к месту размещения new, функция-функция-член() является необязательным требованием для Allocator, поскольку С++ 11.

Для пользовательских распределителей (например, для выравнивания по страницам с использованием memalign), возврат к месту размещения new всегда приводит к правильному поведению?

4b9b3361

Ответ 1

таблица требований распределителя говорит, что construct(c, args), если предоставлено, должен "построить объект типа C в C",

В нем ничего не сказано о 1) какие аргументы должны быть переданы конструктору C или 2), как эти аргументы должны быть переданы. То, что выбор распределителя и на самом деле два распределителя в стандарте беспорядок с аргументами перед передачей их в конструктор C: std::scoped_allocator_adaptor и std::pmr::polymorphic_allocator. При построении std::pair, в частности, аргументы, которые они передают конструктору pair, могут даже не напоминать те, которые они получили.

Нет никаких требований к совершенному переходу; С++ 03-стиль construct(T*, const T&) соответствует, если он неэффективен.

std::allocator construct и destroy устарели, потому что они бесполезны: ни один хороший код С++ 11 и более поздний не должен вызывать их напрямую, и они ничего не добавляют по умолчанию.


Обработка выравнивания памяти должна быть задачей allocate, а не construct.

Ответ 2

Функции были удалены вместе с другими из статьи D0174R0 Устаревание частичной библиотеки в С++ 17. Если мы посмотрим на соответствующий раздел, мы имеем

Многие члены std:: allocator дублируют поведение, которое в противном случае создается std::allocator_traits<allocator<T>>, и его можно безопасно удалить, чтобы упростить этот класс. Кроме того, addressof как свободная функция заменяет std::allocator<T>::address, которая требует объекта-распределителя правильного типа. Наконец, псевдонимы ссылочного типа были первоначально предоставлены в качестве ожидаемого средства для расширения с другими распределителями, но оказались не полезными, когда мы указали требования распределителя (17.6.3.5 [allocator.requirements]).

Пока мы не можем удалить эти элементы, не нарушая совместимость с кодом, явно использующим этот тип распределителя, мы не должны рекомендовать их дальнейшее использование. Если тип хочет поддерживать общие распределители, он должен получить доступ к функциям распределителя через allocator_traits, а не напрямую обращаться к членам распределителя. В противном случае он не будет должным образом поддерживать распределителей, которые полагаются на черты, чтобы синтезировать поведение по умолчанию. Аналогичным образом, если пользователь не намерен поддерживать общие распределители, гораздо проще напрямую вызывать новые, удалять и принимать другие свойства std:: allocator, такие как типы указателей, напрямую.

Акцент на мине

Таким образом, рациональным было то, что нам не нужно дублировать весь код в распределителе, поскольку у нас есть признаки распределителя. Если мы посмотрим на std::allocator_traits, мы увидим, что у него есть

allocate
deallocate
construct
destroy
max_size

статические функции, поэтому мы можем использовать их вместо блоков в распределителе.