std::shared_ptr<T>:: shared_ptr
|
constexpr
shared_ptr
(
)
noexcept
;
|
(1) | |
|
constexpr
shared_ptr
(
std::
nullptr_t
)
noexcept
;
|
(2) | |
|
template
<
class
Y
>
explicit shared_ptr ( Y * ptr ) ; |
(3) | |
|
template
<
class
Y,
class
Deleter
>
shared_ptr ( Y * ptr, Deleter d ) ; |
(4) | |
|
template
<
class
Deleter
>
shared_ptr ( std:: nullptr_t ptr, Deleter d ) ; |
(5) | |
|
template
<
class
Y,
class
Deleter,
class
Alloc
>
shared_ptr ( Y * ptr, Deleter d, Alloc alloc ) ; |
(6) | |
|
template
<
class
Deleter,
class
Alloc
>
shared_ptr ( std:: nullptr_t ptr, Deleter d, Alloc alloc ) ; |
(7) | |
|
template
<
class
Y
>
shared_ptr ( const shared_ptr < Y > & r, element_type * ptr ) noexcept ; |
(8) | |
|
template
<
class
Y
>
shared_ptr ( shared_ptr < Y > && r, element_type * ptr ) noexcept ; |
(8) | (начиная с C++20) |
|
shared_ptr
(
const
shared_ptr
&
r
)
noexcept
;
|
(9) | |
|
template
<
class
Y
>
shared_ptr ( const shared_ptr < Y > & r ) noexcept ; |
(9) | |
|
shared_ptr
(
shared_ptr
&&
r
)
noexcept
;
|
(10) | |
|
template
<
class
Y
>
shared_ptr ( shared_ptr < Y > && r ) noexcept ; |
(10) | |
|
template
<
class
Y
>
explicit shared_ptr ( const std:: weak_ptr < Y > & r ) ; |
(11) | |
|
template
<
class
Y
>
shared_ptr ( std:: auto_ptr < Y > && r ) ; |
(12) | (удалено в C++17) |
|
template
<
class
Y,
class
Deleter
>
shared_ptr ( std:: unique_ptr < Y, Deleter > && r ) ; |
(13) | |
Создает новый
shared_ptr
из различных типов указателей, ссылающихся на управляемый объект.
|
Для целей нижеследующего описания, тип указателя
|
(since C++17) |
shared_ptr
без управляемого объекта, т.е. пустой
shared_ptr
.
shared_ptr
с
ptr
в качестве указателя на управляемый объект.
|
Для
(3,4,6)
,
|
(до C++17) |
|
Если
|
(начиная с C++17) |
T
не является типом массива;
delete
[
]
ptr
если
T
является типом массива
(начиная с C++17)
в качестве удалителя.
Y
должен быть полным типом. Выражение delete должно быть корректным, иметь хорошо определенное поведение и не генерировать исключений.
Этот конструктор дополнительно не участвует в разрешении перегрузки, если выражение delete некорректно.
(начиная с C++17)
|
|
(до C++17) |
|
Эти конструкторы дополнительно не участвуют в разрешении перегрузки, если выражение d ( ptr ) не является корректно сформированным, или если std:: is_move_constructible_v < D > равно false . |
(начиная с C++17) |
Alloc
должен быть
Allocator
.
shared_ptr
, который разделяет информацию о владении с начальным значением
r
, но содержит несвязанный и неуправляемый указатель
ptr
. Если этот
shared_ptr
оказывается последним в группе, выходящим из области видимости, он вызовет сохранённый deleter для изначально управляемого объекта
r
. Однако вызов
get()
на этом
shared_ptr
всегда будет возвращать копию
ptr
. Программист обязан обеспечить, чтобы
ptr
оставался действительным до тех пор, пока существует этот shared_ptr, как в типичных случаях использования, когда
ptr
является членом объекта, управляемого
r
, или является алиасом (например, downcast) для
r.get()
Для второй перегрузки, принимающей rvalue,
r
становится пустым и
r.
get
(
)
==
nullptr
после вызова.
(since C++20)
shared_ptr
, который разделяет владение объектом, управляемым
r
. Если
r
не управляет объектом,
*
this
также не управляет объектом. Шаблонная перегрузка не участвует в разрешении перегрузки, если
Y*
не
неявно преобразуем в
(до C++17)
совместим с
(начиная с C++17)
T*
.
shared_ptr
из
r
. После конструирования
*
this
содержит копию предыдущего состояния
r
,
r
становится пустым и его сохраненный указатель становится нулевым. Шаблонная перегрузка не участвует в разрешении перегрузки, если
Y*
не
неявно преобразуем в
(до C++17)
совместим с
(с C++17)
T*
.
shared_ptr
, который разделяет владение объектом, управляемым
r
.
Y*
должен быть неявно преобразуем в
T*
.
(до C++17)
Эта перегрузка участвует в разрешении перегрузки только если
Y*
совместим с
T*
.
(начиная с C++17)
Заметим, что
r.
lock
(
)
может быть использован для той же цели: разница в том, что этот конструктор выбрасывает исключение если аргумент пуст, тогда как
std::
weak_ptr
<
T
>
::
lock
(
)
создает пустой
std::shared_ptr
в этом случае.
shared_ptr
, который хранит и владеет объектом, ранее принадлежавшим
r
.
Y*
должен быть конвертируемым в
T*
. После конструирования
r
становится пустым.
shared_ptr
, который управляет объектом, в настоящее время управляемым
r
. Делетер, ассоциированный с
r
, сохраняется для будущего удаления управляемого объекта.
r
не управляет никаким объектом после вызова.
Эта перегрузка не участвует в разрешении перегрузки, если
std::unique_ptr<Y, Deleter>::pointer
не
совместим с
T*
.
Если
r.
get
(
)
является нулевым указателем, эта перегрузка эквивалентна конструктору по умолчанию
(1)
.
|
(since C++17) |
Deleter
является ссылочным типом, это эквивалентно
shared_ptr
(
r.
release
(
)
,
std::
ref
(
r.
get_deleter
(
)
)
. В противном случае это эквивалентно
shared_ptr
(
r.
release
(
)
, std
::
move
(
r.
get_deleter
(
)
)
)
.
Когда
T
не является типом массива, перегрузки
(3,4,6)
активируют
shared_from_this
с
ptr
, а перегрузка
(13)
активирует
shared_from_this
с указателем, возвращаемым
r.
release
(
)
.
Содержание |
Параметры
| ptr | - | указатель на управляемый объект |
| d | - | удалитель для уничтожения объекта |
| alloc | - | аллокатор для выделения памяти для внутреннего использования |
| r | - | другой умный указатель для разделения владения или получения владения |
Постусловия
Исключения
T
не является типом массива, и вызывается
delete
[
]
ptr
в противном случае
(начиная с C++17)
.
Примечания
Конструктор
активирует
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.
Перегрузки с сырыми указателями принимают владение объектом, на который указывают. Поэтому создание
shared_ptr
с использованием перегрузки для сырого указателя для объекта, который уже управляется
shared_ptr
, например через
shared_ptr
(
ptr.
get
(
)
)
, вероятно приведёт к неопределённому поведению, даже если объект имеет тип, унаследованный от
std::enable_shared_from_this
.
Поскольку конструктор по умолчанию является
constexpr
, статические shared_ptrs инициализируются как часть
статической нелокальной инициализации
, до начала любой динамической нелокальной инициализации. Это делает безопасным использование shared_ptr в конструкторе любого статического объекта.
В C++11 и C++14 допустимо создавать std:: shared_ptr < T > из std:: unique_ptr < T [ ] > :
std::unique_ptr<int[]> arr(new int[1]); std::shared_ptr<int> ptr(std::move(arr));
` сохранен без изменений, так как содержит C++ код, который не должен переводиться согласно инструкциям. HTML структура и атрибуты также сохранены в оригинальном виде.
Поскольку
shared_ptr
получает свой удалитель (объект
std::
default_delete
<
T
[
]
>
) из
std::unique_ptr
, массив будет корректно освобожден.
Это больше не разрешено в C++17. Вместо этого следует использовать форму массива std:: shared_ptr < T [ ] > .
Пример
#include <iostream> #include <memory> struct Foo { int id{0}; Foo(int i = 0) : id{i} { std::cout << "Foo::Foo(" << i << ")\n"; } ~Foo() { std::cout << "Foo::~Foo(), id=" << id << '\n'; } }; struct D { void operator()(Foo* p) const { std::cout << "Call delete from function object. Foo::id=" << p->id << '\n'; delete p; } }; int main() { { std::cout << "1) constructor with no managed object\n"; std::shared_ptr<Foo> sh1; } { std::cout << "2) constructor with object\n"; std::shared_ptr<Foo> sh2(new Foo{10}); std::cout << "sh2.use_count(): " << sh2.use_count() << '\n'; std::shared_ptr<Foo> sh3(sh2); std::cout << "sh2.use_count(): " << sh2.use_count() << '\n'; std::cout << "sh3.use_count(): " << sh3.use_count() << '\n'; } { std::cout << "3) constructor with object and deleter\n"; std::shared_ptr<Foo> sh4(new Foo{11}, D()); std::shared_ptr<Foo> sh5(new Foo{12}, [](auto p) { std::cout << "Call delete from lambda... p->id=" << p->id << '\n'; delete p; }); } }
Вывод:
1) constructor with no managed object 2) constructor with object Foo::Foo(10) sh2.use_count(): 1 sh2.use_count(): 2 sh3.use_count(): 2 Foo::~Foo(), id=10 3) constructor with object and deleter Foo::Foo(11) Foo::Foo(12) Call delete from lambda... p->id=12 Foo::~Foo(), id=12 Call delete from function object. Foo::id=11 Foo::~Foo(), id=11
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 3548 | C++11 |
the constructor from
unique_ptr
copy-constructed the deleter
|
move-constructs instead |
Смотрите также
|
создает shared pointer, который управляет новым объектом
(шаблон функции) |
|
|
создает shared pointer, который управляет новым объектом, выделенным с использованием аллокатора
(шаблон функции) |
|
|
(C++11)
|
позволяет объекту создавать
shared_ptr
ссылающийся на себя
(шаблон класса) |