Spec-Zone.ru › C++

std::allocate_shared, std::allocate_shared_for_overwrite

Определено в заголовке <memory>
template< class T, class Alloc, class... Args >
shared_ptr<T> allocate_shared( const Alloc& alloc, Args&&... args );
(1) (с C++11)
(T — не массив)
template< class T, class Alloc >
shared_ptr<T> allocate_shared( const Alloc& alloc, std::size_t N );
(2) (с C++20)
(T — U[])
template< class T, class Alloc >
shared_ptr<T> allocate_shared( const Alloc& alloc );
(3) (с C++20)
(T — U[N])
template< class T, class Alloc >
shared_ptr<T> allocate_shared( const Alloc& alloc, std::size_t N,
                               const std::remove_extent_t<T>& u );
(4) (с C++20)
(T — U[])
template< class T, class Alloc >
shared_ptr<T> allocate_shared( const Alloc& alloc,
                               const std::remove_extent_t<T>& u );
(5) (с C++20)
(T — U[N])
template< class T, class Alloc >
shared_ptr<T> allocate_shared_for_overwrite( const Alloc& alloc );
(6) (с C++20)
(T — не U[])
template< class T, class Alloc >
shared_ptr<T> allocate_shared_for_overwrite( const Alloc& alloc, std::size_t N );
(7) (с C++20)
(T — U[])
1) Конструирует объект типа T и оборачивает его в std::shared_ptr, используя args в качестве списка параметров для конструктора T. Объект конструируется так же, как в выражении ::new (pv) T(v)(до C++20)std::allocator_traits<A2>::construct(a, pv, v)(с C++20), где pv — внутренний указатель void* на хранилище, подходящее для объекта типа T, а a — копия распределителя, перенастроенного на std::remove_cv_t<T>. Хранилище обычно больше, чем sizeof(T), чтобы использовать одно выделение памяти для блока управления shared указателем и объекта T. Конструктор std::shared_ptr, вызываемый этой функцией, позволяет shared_from_this с указателем на только что созданный объект типа T. Все выделения памяти выполняются с копией alloc, которая должна удовлетворять требованиям Allocator.
2,3) То же, что (1), но создаваемый объект — это, возможно, многомерный массив, каждый элемент которого (не являющийся массивом) инициализируется, как если бы выражением std::allocator_traits<A2>::construct(a2, pv), где a2 типа A2 — копия распределителя, перенастроенная для управления объектами типа std::remove_cv_t<std::remove_all_extents_t<T>>. Перегрузка (2) создаёт массив размером N вдоль первого измерения. Элементы массива инициализируются в порядке возрастания их адресов, а когда их жизненный цикл заканчивается, они уничтожаются в обратном порядке их первоначального построения.
4,5) То же, что (2,3), но элементы массива инициализируются значениями по умолчанию u. Если std::remove_extent_t<T> сам по себе не является типом массива, это выполняется как если бы выражение распределителя совпадало с (1), за исключением того, что распределитель перенастраивается на std::remove_cv_t<std::remove_all_extents_t<T>>. В противном случае это выполняется как если бы каждый элемент (не являющийся массивом) (возможно, многомерного) массива был инициализирован соответствующим элементом из u с использованием того же выражения распределителя, что и в (1), за исключением того, что распределитель перенастраивается на тип std::remove_cv_t<std::remove_all_extents_t<T>>. Перегрузка (4) создаёт массив размером N вдоль первого измерения. Элементы массива инициализируются в порядке возрастания их адресов, а когда их жизненный цикл заканчивается, они уничтожаются в обратном порядке их первоначального построения.
6) То же, что (1), если T не является массивом, и (3), если T — U[N], за исключением того, что создаваемый объект инициализируется по умолчанию.
7) То же, что (2), за исключением того, что отдельные элементы массива инициализируются по умолчанию.

Для allocate_shared, объект (или отдельные элементы массива для (2-5))(с C++20) уничтожаются с помощью выражения std::allocator_traits<A2>::destroy(a, p), где p — указатель на объект, а a — копия распределителя, переданного в allocate_shared, перенастроенный на тип уничтожаемого объекта.

Для allocate_shared_for_overwrite, объект (или отдельные элементы, если T — тип массива) будет уничтожен посредством p->~X(), где p — указатель на объект, а X — его тип.

(с C++20)

Параметры

alloc - используемый распределитель
args... - список аргументов, с помощью которых будет создан экземпляр T
N - размер массива
u - начальное значение для инициализации каждого элемента массива

Возвращаемое значение

Указатель на экземпляр типа T.

Исключения

Может бросить исключения, выброшенные Alloc::allocate() или конструктором T. Если исключение брошено, (1) не оказывает никакого эффекта. Если исключение брошено во время построения массива, уже проинициализированные элементы уничтожаются в обратном порядке.(с C++20)

Примечания

Подобно std::make_shared, эта функция обычно выполняет только одно выделение и помещает как объект T, так и блок управления в выделенный блок памяти (стандарт рекомендует, но не требует этого, все известные реализации это делают). Копия alloc хранится в составе блока управления, чтобы её можно было использовать для освобождения памяти, когда счётчики общих и слабых ссылок достигнут нуля.

В отличие от std::shared_ptr constructors, std::allocate_shared не принимает отдельный пользовательский деструктор: используемый распределитель используется для уничтожения блока управления и объекта T, а также для освобождения их общего блока памяти.

std::shared_ptr поддерживает типы массивов (начиная с C++17), но std::allocate_shared не поддерживает. Эта функциональность поддерживается boost::allocate_shared.

(до C++20)

Конструктор активирует shared_from_this с указателем ptr типа U* означает, что он определяет, имеет ли U явную и доступную(с C++17) базовую специализацию std::enable_shared_from_this, и если да, то конструктор оценивает утверждение:

if (ptr != nullptr && ptr->weak_this.expired())
    ptr->weak_this = std::shared_ptr<std::remove_cv_t<U>>(
                         *this, const_cast<std::remove_cv_t<U>*>(ptr));

Где weak_this — скрытый мутабельный член std::weak_ptr объекта std::enable_shared_from_this. Присвоение члена weak_this не является атомарным и конфликтует с любым потенциальным одновременным доступом к тому же объекту. Это гарантирует, что будущие вызовы shared_from_this() будут совмещать владение с std::shared_ptr созданным этим указателем.

Проверка ptr->weak_this.expired() в демонстрационном коде выше гарантирует, что weak_this не переприсваивается, если уже указывает владельца. Эта проверка необходима начиная с C++17.

Макроинструкция проверки наличия функции Значение Std Функция
__cpp_lib_smart_ptr_for_overwrite 202002L (C++20) Создание интеллектуальных указателей с инициализацией по умолчанию (std::allocate_shared_for_overwrite, std::make_shared_for_overwrite, std::make_unique_for_overwrite); перегрузки (6,7)

Пример

См. также

(конструктор)
создаёт новый shared_ptr
(публичный член-функция)
make_sharedmake_shared_for_overwrite
(C++20)
создаёт shared указатель, управляющий новым объектом
(функция-шаблон)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/memory/shared_ptr/allocate_shared

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API