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) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared ( const Alloc & alloc, std:: size_t N ) ; |
(2) | (начиная с C++20) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared ( const Alloc & alloc ) ; |
(3) | (начиная с C++20) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared
(
const
Alloc
&
alloc,
std::
size_t
N,
|
(4) | (начиная с C++20) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared
(
const
Alloc
&
alloc,
|
(5) | (начиная с C++20) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared_for_overwrite ( const Alloc & alloc ) ; |
(6) | (начиная с C++20) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared_for_overwrite
(
const
Alloc
&
alloc,
|
(7) | (начиная с C++20) |
Выделяет память для объекта, используя копию
alloc
(пересвязанную для неопределённого
value_type
), и инициализирует объект предоставленными аргументами. Возвращает объект
std::shared_ptr
, управляющий вновь созданным объектом.
T
и конструируется как если бы с помощью
std::
allocator_traits
<
Alloc
>
::
construct
( a, pt, ( std:: forward < Args > ( args ) ... ) , где pt является указателем std:: remove_cv_t < T < * на область памяти, подходящую для хранения объекта типа std:: remove_cv_t < T > . Если объект должен быть уничтожен, он уничтожается как если бы с помощью std:: allocator_traits < Alloc > :: destroy ( a, pt ) , где pt является указателем на этот объект типа std:: remove_cv_t < T > .
Alloc
и является потенциально пересвязанной копией
alloc
.
|
Эта перегрузка участвует в разрешении перегрузки только если
|
(since C++20) |
T
является типом неограниченного массива.
T
. Каждый элемент имеет значение по умолчанию.
T
является типом ограниченного массива.
T
является типом неограниченного массива.
T
. Каждый элемент имеет начальное значение
u
.
T
является типом ограниченного массива.
T
.
-
Если
Tне является типом массива, объект конструируется как если бы с помощью :: new ( pv ) T , где pv — это указатель типа void * на область памяти, подходящую для хранения объекта типаT. Если объект должен быть уничтожен, он уничтожается как если бы с помощью pt - > ~T ( ) , где pt — это указатель на данный объект типаT. -
Если
Tявляется типом ограниченного массива, начальное значение каждого элемента не определено.
T
не является типом массива или является типом ограниченного массива.
T
является типом неограниченного массива.
Инициализация и уничтожение элементов массива
В приведённом ниже описании,
a
имеет тип
Элементы массива типа
2,3)
std::
allocator_traits
<
Alloc
>
::
construct
(
a, pu
)
4,5)
std::
allocator_traits
<
Alloc
>
::
construct
(
a, pu, u
)
6,7)
::
new
(
pv
)
U
Когда время жизни объекта, управляемого возвращаемым std::shared_ptr , заканчивается, или когда инициализация элемента массива выбрасывает исключение, инициализированные элементы уничтожаются в обратном порядке их первоначального конструирования.
Для каждого элемента массива не-массивного типа
2-5)
std::
allocator_traits
<
Alloc
>
::
destroy
(
a, pu
)
, где
pu
является
U
*
указателем на этот элемент массива типа
U
6,7)
pu
-
>
~U
(
)
, где
pu
является указателем на этот элемент массива типа
U
|
(начиная с C++20) |
Параметры
| alloc | - | используемый Allocator |
| args... | - |
список аргументов для конструирования экземпляра
T
|
| N | - | используемый размер массива |
| u | - | начальное значение для инициализации каждого элемента массива |
Возвращаемое значение
std::shared_ptr
к объекту типа
T
или
std::
remove_extent_t
<
T
>
[
N
]
если
T
является типом неограниченного массива
(начиная с C++20)
.
Для возвращённого std::shared_ptr r , r. get ( ) возвращает ненулевой указатель, а r. use_count ( ) возвращает 1 .
Исключения
Может выбрасывать исключения, выброшенные из
Alloc
::
allocate
(
)
или из конструктора
T
. Если исключение выброшено,
(1)
не имеет эффекта.
Если исключение выброшено во время конструирования массива, уже проинициализированные элементы уничтожаются в обратном порядке
(since C++20)
.
Примечания
Эти функции обычно выделяют больше памяти, чем sizeof ( T ) чтобы обеспечить место для внутренних структур служебной информации, таких как счетчики ссылок.
Подобно
std::make_shared
, эта функция обычно выполняет только одно выделение памяти и размещает как объект
T
, так и блок управления в выделенном блоке памяти (стандарт рекомендует, но не требует этого, все известные реализации делают именно так). Копия
alloc
сохраняется как часть блока управления, чтобы её можно было использовать для освобождения памяти после того, как счётчики сильных и слабых ссылок достигнут нуля.
В отличие от
std::shared_ptr
constructors
,
std::allocate_shared
не принимает отдельный пользовательский deleter: предоставленный аллокатор используется для разрушения блока управления и объекта
T
, а также для освобождения их общего блока памяти.
|
std::shared_ptr
поддерживает массивы (начиная с C++17), но
|
(до 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
не является атомарной операцией и конфликтует с любыми потенциально параллельными обращениями к тому же объекту. Это гарантирует, что последующие вызовы
shared_from_this()
будут разделять владение с
std::shared_ptr
, созданным данным конструктором из сырого указателя.
Тест
ptr
-
>
weak_this
.
expired
(
)
в приведённом коде гарантирует, что
weak_this
не будет переназначен, если он уже указывает на владельца. Этот тест обязателен начиная с C++17.
| Макрос тестирования возможностей | Значение | Стандарт | Функция |
|---|---|---|---|
__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
)
|
Пример
#include <cstddef> #include <iostream> #include <memory> #include <memory_resource> #include <vector> class Value { int i; public: Value(int i) : i(i) { std::cout << "Value(), i = " << i << '\n'; } ~Value() { std::cout << "~Value(), i = " << i << '\n'; } void print() const { std::cout << "i = " << i << '\n'; } }; int main() { // Создание полиморфного аллокатора с использованием монотонного буферного ресурса std::byte buffer[sizeof(Value) * 8]; std::pmr::monotonic_buffer_resource resource(buffer, sizeof(buffer)); std::pmr::polymorphic_allocator<Value> allocator(&resource); std::vector<std::shared_ptr<Value>> v; for (int i{}; i != 4; ++i) // Использование std::allocate_shared с пользовательским аллокатором v.emplace_back(std::allocate_shared<Value>(allocator, i)); for (const auto& sp : v) sp->print(); } //< Все умные указатели автоматически очистятся при выходе из области видимости.
Вывод:
Value(), i = 0 Value(), i = 1 Value(), i = 2 Value(), i = 3 i = 0 i = 1 i = 2 i = 3 ~Value(), i = 0 ~Value(), i = 1 ~Value(), i = 2 ~Value(), i = 3
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 3216 | C++20 |
std::allocate_shared
всегда перепривязывал
аллокатор перед созданием и уничтожением объектов |
перепривязка опциональна |
| LWG 4024 | C++20 |
было неясно, как уничтожаются объекты, созданные в
std::allocate_shared_for_overwrite
|
прояснено |
Смотрите также
создает новый
shared_ptr
(public member function) |
|
|
создает shared pointer, который управляет новым объектом
(function template) |