Namespaces
Variants

std::shared_ptr<T>:: shared_ptr

From cppreference.net
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
**Примечание:** В данном случае переводить нечего, так как весь текст внутри тегов ` ` представляет собой C++ код, который согласно инструкциям не подлежит переводу. HTML-разметка и атрибуты также сохранены без изменений. (Примечание: В данном фрагменте HTML отсутствует текстовое содержимое для перевода - присутствуют только HTML-теги и атрибуты, которые согласно инструкциям не подлежат переводу)
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 из различных типов указателей, ссылающихся на управляемый объект.

Для целей нижеследующего описания, тип указателя Y* считается совместимым с типом указателя T* если либо Y* конвертируем в T* , либо Y является типом массива U[N] и T является U cv [] (где cv - некоторый набор cv-квалификаторов).

(since C++17)
1,2) Создает shared_ptr без управляемого объекта, т.е. пустой shared_ptr .
3-7) Создает shared_ptr с ptr в качестве указателя на управляемый объект.

Для (3,4,6) , Y* должен быть преобразуем в T* .

(до C++17)

Если T является типом массива U[N] , (3,4,6) не участвуют в разрешении перегрузки, если Y(*)[N] является недопустимым типом или не преобразуется в T* . Если T является типом массива U[] , (3,4,6) не участвуют в разрешении перегрузки, если Y(*)[] является недопустимым типом или не преобразуется в T* . В противном случае, (3,4,6) не участвуют в разрешении перегрузки, если Y* не преобразуется в T* .

(начиная с C++17)
Дополнительно:
3) Использует delete-expression delete ptr если T не является типом массива; delete [ ] ptr если T является типом массива (начиная с C++17) в качестве удалителя. Y должен быть полным типом. Выражение delete должно быть корректным, иметь хорошо определенное поведение и не генерировать исключений. Этот конструктор дополнительно не участвует в разрешении перегрузки, если выражение delete некорректно. (начиная с C++17)
4,5) Использует указанный удалитель d в качестве удалителя. Выражение d ( ptr ) должно быть корректно сформированным, иметь хорошо определённое поведение и не генерировать исключений. Конструкция d и сохранённого удалителя, скопированного из него, не должна генерировать исключения.

Deleter должен быть CopyConstructible .

(до C++17)

Эти конструкторы дополнительно не участвуют в разрешении перегрузки, если выражение d ( ptr ) не является корректно сформированным, или если std:: is_move_constructible_v < D > равно false .

(начиная с C++17)
6,7) То же, что (4,5) , но дополнительно использует копию alloc для выделения данных для внутреннего использования. Alloc должен быть Allocator .
8) Алиасинг-конструктор : создаёт 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)
9) Создает shared_ptr , который разделяет владение объектом, управляемым r . Если r не управляет объектом, * this также не управляет объектом. Шаблонная перегрузка не участвует в разрешении перегрузки, если Y* не неявно преобразуем в (до C++17) совместим с (начиная с C++17) T* .
10) Перемещающий конструктор создает shared_ptr из r . После конструирования * this содержит копию предыдущего состояния r , r становится пустым и его сохраненный указатель становится нулевым. Шаблонная перегрузка не участвует в разрешении перегрузки, если Y* не неявно преобразуем в (до C++17) совместим с (с C++17) T* .
11) Создает shared_ptr , который разделяет владение объектом, управляемым r . Y* должен быть неявно преобразуем в T* . (до C++17) Эта перегрузка участвует в разрешении перегрузки только если Y* совместим с T* . (начиная с C++17) Заметим, что r. lock ( ) может быть использован для той же цели: разница в том, что этот конструктор выбрасывает исключение если аргумент пуст, тогда как std:: weak_ptr < T > :: lock ( ) создает пустой std::shared_ptr в этом случае.
12) Создает shared_ptr , который хранит и владеет объектом, ранее принадлежавшим r . Y* должен быть конвертируемым в T* . После конструирования r становится пустым.
13) Создает 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 - другой умный указатель для разделения владения или получения владения

Постусловия

1,2) use_count() равно 0 и get() равно nullptr .
3-7) use_count() равно 1 и get() равно ptr .
8) get() равен ptr . Для второй перегрузки, r пуст и r. get ( ) равен nullptr .
9) get() равно r. get ( ) и use_count() равно r. use_count ( ) .
10) r должен быть пустым и r. get ( ) должен равняться nullptr , а * this должен быть старым значением r .
11) use_count() равен r. use_count ( ) .
12) use_count() равен 1 и r. get ( ) равен nullptr .

Исключения

3) std::bad_alloc если требуемая дополнительная память не может быть получена. Может выбрасывать реализационно-определённое исключение для других ошибок. Если возникает исключение, вызывается delete ptr если T не является типом массива, и вызывается delete [ ] ptr в противном случае (начиная с C++17) .
4-7) std::bad_alloc если не удалось получить необходимую дополнительную память. Может выбрасывать реализационно-определённое исключение для других ошибок. d ( ptr ) вызывается при возникновении исключения.
11) std::bad_weak_ptr если r. expired ( ) == true . В этом случае конструктор не имеет эффекта.
12) std::bad_alloc если не удалось получить необходимую дополнительную память. Может выбрасывать реализационно-определённое исключение для других ошибок. Этот конструктор не имеет эффекта, если возникает исключение.
13) Если возникает исключение, конструктор не имеет эффекта.

Примечания

Конструктор активирует 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, который управляет новым объектом, выделенным с использованием аллокатора
(шаблон функции)
позволяет объекту создавать shared_ptr ссылающийся на себя
(шаблон класса)