23 General utilities library [utilities]

23.11 Smart pointers [smartptr]

23.11.2 Shared-ownership pointers [util.smartptr]

23.11.2.2 Class template shared_­ptr [util.smartptr.shared]

23.11.2.2.1 shared_­ptr constructors [util.smartptr.shared.const]

В определениях конструктора, приведенных ниже, включение shared_­from_­this with pдля указателя p типа Y*означает, что при Y наличии однозначного и доступного базового класса, который является специализацией enable_­shared_­from_­this, то он remove_­cv_­t<Y>* должен быть неявно преобразован в, T* и конструктор оценивает оператор:

if (p != nullptr && p->weak_this.expired())
  p->weak_this = shared_ptr<remove_cv_t<Y>>(*this, const_cast<remove_cv_t<Y>*>(p));

Присвоение weak_­this члену не является атомарным и конфликтует с любым потенциально одновременным доступом к тому же объекту ([intro.multithread]).

constexpr shared_ptr() noexcept;

Effects: Создает пустой shared_­ptr объект.

Postconditions: use_­count() == 0 && get() == nullptr.

template<class Y> explicit shared_ptr(Y* p);

Requires: Y должен быть законченным типом. Выражение delete[] p, когда T является типом массива или delete p, когда T не является типом массива, должно иметь четко определенное поведение и не должно вызывать исключений.

Effects: Когда T не является типом массива, создает shared_­ptr объект, которому принадлежит указатель p. В противном случае создает объект- shared_­ptr владелец p и вызывающий объект удаления неопределенного типа delete[] p. Когда T не является типом массива, включается shared_­from_­this с помощью p. Если выбрасывается исключение, вызывается, delete p если T он не является типом массива, в delete[] p противном случае.

Postconditions: use_­count() == 1 && get() == p.

Throws: bad_­allocили исключение, определяемое реализацией, когда не удалось получить ресурс, отличный от памяти.

Remarks: Когда T является типом массива, этот конструктор не должен участвовать в разрешении перегрузки, если выражение не delete[] p имеет правильного формата и либо T является U[N] и Y(*)[N] может быть преобразовано в T*, либо T является U[] и Y(*)[] может быть преобразовано в T*. Когда T не является типом массива, этот конструктор не должен участвовать в разрешении перегрузки, если выражение не delete p имеет правильного формата и не Y* может быть преобразовано в T*.

template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template <class D> shared_ptr(nullptr_t p, D d); template <class D, class A> shared_ptr(nullptr_t p, D d, A a);

Requires: Создание d и удаление типа, D инициализированного с помощью std​::​move(d) , не должны вызывать исключений. Выражение d(p) должно иметь четко определенное поведение и не должно вызывать исключений. A должен быть распределителем ([allocator.requirements]).

Effects: Создает shared_­ptr объект, которому принадлежит объект p и средство удаления d. Когда T это не массив, первый и второй конструкторы активируются shared_­from_­this с помощью p. Второй и четвертый конструкторы должны использовать копию a для выделения памяти для внутреннего использования. Если выбрасывается исключение, d(p) вызывается.

Postconditions: use_­count() == 1 && get() == p.

Throws: bad_­allocили исключение, определяемое реализацией, когда не удалось получить ресурс, отличный от памяти.

Remarks: Когда T это тип массива, этот конструктор не будет участвовать в разрешении перегрузки , если is_­move_­constructible_­v<D> нет true, то выражение d(p) хорошо сформирован, и либо T это U[N] и Y(*)[N] превращена в T*или T вне U[] и Y(*)[] конвертируется в T*. Когда T это не тип массива, этот конструктор не должен участвовать в разрешении перегрузки , если is_­move_­constructible_­v<D> не trueвыражение d(p) хорошо сформировано, и Y* конвертируются в T*.

template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;

Effects: Создает shared_­ptr экземпляр, который хранит p и разделяет владение r.

Postconditions: get() == p && use_­count() == r.use_­count().

[ Note: Чтобы избежать возможности появления висячего указателя, пользователь этого конструктора должен убедиться, что он p остается действительным, по крайней мере, до тех пор, пока группа владения не r будет уничтожена. ] end note

[ Note: Этот конструктор позволяет создавать пустой shared_­ptr экземпляр с сохраненным указателем, отличным от NULL. ] end note

shared_ptr(const shared_ptr& r) noexcept; template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;

Remarks: Второй конструктор не должен участвовать в разрешении перегрузки, если он Y* не совместим с T*.

Effects: Если r пусто, создает пустой shared_­ptr объект; в противном случае создает shared_­ptr объект, с которым совместно владеет r.

Postconditions: get() == r.get() && use_­count() == r.use_­count().

shared_ptr(shared_ptr&& r) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;

Remarks: Второй конструктор не должен участвовать в разрешении перегрузки, если он Y* не совместим с T*.

Effects: Move создает shared_­ptr экземпляр из r.

Postconditions: *this должен содержать старое значение r. r будет пустым. r.get() == nullptr.

template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);

Effects: Создает shared_­ptr объект, который разделяет владение r и хранит копию указателя, хранящегося в r. Если выбрасывается исключение, конструктор не действует.

Postconditions: use_­count() == r.use_­count().

Throws: bad_­weak_­ptr когда r.expired().

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если он Y* не совместим с T*.

template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если Y* не совместим с T* и unique_­ptr<Y, D>​::​pointer конвертируется в element_­type*.

Effects: Если r.get() == nullptrэквивалентно shared_­ptr(). В противном случае, если D это не ссылочный тип, эквивалентный shared_­ptr(r.release(), r.get_­deleter()). В противном случае эквивалентно shared_­ptr(r.release(), ref(r.get_­deleter())). Если выбрасывается исключение, конструктор не действует.