A unique pointer - это объект, который владеет другим объектом и управляет этим другим объектом с помощью указателя. Точнее, уникальный указатель - это объект, u который хранит указатель на второй объект p и будет удален, p когда u сам будет уничтожен (например, при выходе из области видимости блока ([stmt.dcl])). В этом контексте u говорят own p.
Механизм , с помощью которого u распоряжается p известно как p«ы связаны deleter, функциональный объект , чей правильный вызов приводит к p» с соответствующим расположением ( как правило , его удаление).
Пусть обозначение u.p обозначает указатель, хранящийся в u, и пусть u.d обозначает связанный с ним удалитель. По запросу u может reset (заменить) u.p и u.d другим указателем и средством удаления, но должен должным образом удалить принадлежащий ему объект с помощью связанного средства удаления, прежде чем такая замена будет считаться завершенной.
Дополнительно u может по запросу transfer ownership на другой уникальный указатель u2. По завершении такой передачи выполняются следующие постусловия:
u2.p равно предварительной передаче u.p,
u.p равно nullptr, и
если u.d состояние сохранялось до передачи , такое состояние было переведено в u2.d.
Как и в случае сброса, он u2 должен должным образом избавиться от объекта, принадлежащего ему до передачи, через связанный с ним удалитель до передачи, прежде чем передача права собственности будет считаться завершенной. [ Note: Состояние удалителя никогда не нужно копировать, его нужно только перемещать или менять местами по мере передачи права собственности. ] — end note
Каждый объект типа, U созданный из unique_ptr шаблона, указанного в этом подпункте, имеет строгую семантику владения уникальным указателем, указанную выше. В частичном удовлетворении этой семантики каждое такое U есть MoveConstructible и MoveAssignable, но не является CopyConstructible ни CopyAssignable. Параметр шаблона T из unique_ptr может быть неполным типом.
[ Note: Использование unique_ptr включает обеспечение безопасности исключений для динамически выделяемой памяти, передачу права собственности на динамически выделяемую память функции и возврат динамически выделенной памяти из функции. ] — end note
namespace std {
template<class T> struct default_delete;
template<class T> struct default_delete<T[]>;
template<class T, class D = default_delete<T>> class unique_ptr;
template<class T, class D> class unique_ptr<T[], D>;
template<class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
template<class T> unique_ptr<T> make_unique(size_t n);
template<class T, class... Args> unspecified make_unique(Args&&...) = delete;
template<class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
template<class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template<class T1, class D1, class T2, class D2>
bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template<class T1, class D1, class T2, class D2>
bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template<class T1, class D1, class T2, class D2>
bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template<class T1, class D1, class T2, class D2>
bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template<class T1, class D1, class T2, class D2>
bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T, class D>
bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D>
bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept;
template <class T, class D>
bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D>
bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept;
template <class T, class D>
bool operator<(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator<(nullptr_t, const unique_ptr<T, D>& y);
template <class T, class D>
bool operator<=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator<=(nullptr_t, const unique_ptr<T, D>& y);
template <class T, class D>
bool operator>(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator>(nullptr_t, const unique_ptr<T, D>& y);
template <class T, class D>
bool operator>=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator>=(nullptr_t, const unique_ptr<T, D>& y);
}
Шаблон класса default_delete служит средством удаления (политика уничтожения) по умолчанию для шаблона класса unique_ptr.
namespace std { template <class T> struct default_delete { constexpr default_delete() noexcept = default; template <class U> default_delete(const default_delete<U>&) noexcept; void operator()(T*) const; }; }
template <class U> default_delete(const default_delete<U>& other) noexcept;
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если он не U* может быть неявно преобразован в T*.
void operator()(T* ptr) const;
namespace std { template <class T> struct default_delete<T[]> { constexpr default_delete() noexcept = default; template <class U> default_delete(const default_delete<U[]>&) noexcept; template <class U> void operator()(U* ptr) const; }; }
template <class U> default_delete(const default_delete<U[]>& other) noexcept;
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если он не U(*)[] может быть преобразован в T(*)[].
template <class U> void operator()(U* ptr) const;
namespace std { template <class T, class D = default_delete<T>> class unique_ptr { public: using pointer = see below; using element_type = T; using deleter_type = D; // [unique.ptr.single.ctor], constructors constexpr unique_ptr() noexcept; explicit unique_ptr(pointer p) noexcept; unique_ptr(pointer p, see below d1) noexcept; unique_ptr(pointer p, see below d2) noexcept; unique_ptr(unique_ptr&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept; template <class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept; // [unique.ptr.single.dtor], destructor ~unique_ptr(); // [unique.ptr.single.asgn], assignment unique_ptr& operator=(unique_ptr&& u) noexcept; template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; unique_ptr& operator=(nullptr_t) noexcept; // [unique.ptr.single.observers], observers add_lvalue_reference_t<T> operator*() const; pointer operator->() const noexcept; pointer get() const noexcept; deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept; explicit operator bool() const noexcept; // [unique.ptr.single.modifiers], modifiers pointer release() noexcept; void reset(pointer p = pointer()) noexcept; void swap(unique_ptr& u) noexcept; // disable copy from lvalue unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; }; }
Тип по умолчанию для параметра шаблона D - default_delete. Аргумент шаблона, предоставляемый клиентом, D должен быть function object typeссылкой lvalue на функцию или ссылкой lvalue на тип объекта функции, для которого, учитывая значение d типа D и значение ptr типа unique_ptr<T, D>::pointer, выражение d(ptr) является действительным и имеет эффект удаления указателя как подходит для этого удалителя.
Если тип удалителя D не является ссылочным типом, он D должен удовлетворять требованиям Destructible.
Если qualified-id remove_reference_t<D>::pointer действительно и обозначает тип ([temp.deduct]), то unique_ptr<T, D>::pointer должно быть синонимом для remove_reference_t<D>::pointer. В противном случае unique_ptr<T, D>::pointer будет синонимом element_type*. Тип unique_ptr<T, D>::pointer должен удовлетворять требованиям NullablePointer.
[ Example: Принимая во внимание тип распределителя X ([allocator.requirements]) и позволяя A быть синонимом allocator_traits<X>, типов A::pointer, A::const_pointer, A::void_pointerи A::const_void_pointer могут быть использованы в качестве unique_ptr<T, D>::pointer. ] — end example
constexpr unique_ptr() noexcept;
constexpr unique_ptr(nullptr_t) noexcept;
Requires: D должны удовлетворять требованиям DefaultConstructible, и эта конструкция не должна вызывать исключения.
Effects: Создает unique_ptr объект, который ничего не владеет, инициализируя значение сохраненного указателя и сохраненного средства удаления.
Remarks: Если is_pointer_v<deleter_type> есть true или is_default_constructible_v<deleter_type> есть false, этот конструктор не должен участвовать в разрешении перегрузки.
explicit unique_ptr(pointer p) noexcept;
Requires: D должны удовлетворять требованиям DefaultConstructible, и эта конструкция не должна вызывать исключения.
Effects: Создает объект, unique_ptr который владеет p, инициализируя сохраненный указатель p и инициализируя значение сохраненного средства удаления.
Remarks: Если is_pointer_v<deleter_type> есть true или is_default_constructible_v<deleter_type> есть false, этот конструктор не должен участвовать в разрешении перегрузки. Если deduction ([over.match.class.deduct]) аргумента шаблона класса выберет шаблон функции, соответствующий этому конструктору, то программа сформирована неправильно.
unique_ptr(pointer p, see below d1) noexcept;
unique_ptr(pointer p, see below d2) noexcept;
Подпись этих конструкторов зависит от того, D является ли это ссылочным типом. Если D это не ссылочный тип A, то подписи:
unique_ptr(pointer p, const A& d) noexcept; unique_ptr(pointer p, A&& d) noexcept;
Если D это ссылочный тип lvalue A&, то подписи будут следующими:
unique_ptr(pointer p, A& d) noexcept; unique_ptr(pointer p, A&& d) = delete;
Если D это ссылочный тип lvalue const A&, то подписи будут следующими:
unique_ptr(pointer p, const A& d) noexcept; unique_ptr(pointer p, const A&& d) = delete;
Effects: Создает unique_ptr объект, которому принадлежит p, инициализируя сохраненный указатель p и инициализируя средство удаления из std::forward<decltype(d)>(d).
Remarks: Эти конструкторы не должны участвовать в разрешении перегрузки , если is_constructible_v<D, decltype(d)> не true.
Postconditions: get() == p. get_deleter() возвращает ссылку на сохраненный удалитель. Если D является ссылочным типом, get_deleter() возвращает ссылку на lvalue d.
Remarks: Если аргумент deduction ([over.match.class.deduct]) шаблона класса выберет шаблон функции, соответствующий любому из этих конструкторов, то программа сформирована неправильно.
[ Example:
D d; unique_ptr<int, D> p1(new int, D()); // D must be MoveConstructible unique_ptr<int, D> p2(new int, d); // D must be CopyConstructible unique_ptr<int, D&> p3(new int, d); // p3 holds a reference to d unique_ptr<int, const D&> p4(new int, D()); // error: rvalue deleter object combined // with reference deleter type
— end example ]
unique_ptr(unique_ptr&& u) noexcept;
Requires: Если D не является эталонным типом, он D должен удовлетворять требованиям MoveConstructible. Построение удалителя из rvalue типа D не должно вызывать исключения.
Effects: Создает unique_ptr путем передачи права собственности от u к *this. Если D это ссылочный тип, это средство удаления является копией, созданной из средства uудаления; в противном случае этот удалитель uсоздается на основе удалителя. [ Note: Конструктор удаления может быть реализован с помощью std::forward<D>. ] — end note
Postconditions: get() дает значение, u.get() полученное до строительства. get_deleter() возвращает ссылку на сохраненный удалитель, созданный из u.get_deleter(). Если D это ссылочный тип, то оба ссылаются на одинget_deleter() и u.get_deleter() тот же удалитель lvalue.
template <class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept;
Requires: Если E это не ссылочный тип, построение удалителя из rvalue типа E должно быть правильно сформировано и не должно вызывать исключения. В противном случае E является ссылочным типом, и конструкция удалителя из lvalue типа E должна быть правильно сформирована и не должна вызывать исключения.
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если:
unique_ptr<U, E>::pointer неявно конвертируется в pointer,
U не является типом массива и
либо D является ссылочным типом и E относится к тому же типу D, либо D не является ссылочным типом и E может неявно преобразовываться в D.
Effects: Создает unique_ptr путем передачи права собственности от u к *this. Если E это ссылочный тип, это средство удаления является копией, созданной из средства uудаления; в противном случае этот удалитель uсоздается на основе удалителя. [ Note: Конструктор удаления может быть реализован с помощью std::forward<E>. ] — end note
~unique_ptr();
Requires: Выражение get_deleter()(get()) должно быть правильно сформировано, иметь четко определенное поведение и не должно вызывать исключений. [ Note: Использование default_delete требует T полного типа. ] — end note
unique_ptr& operator=(unique_ptr&& u) noexcept;
Requires: Если D не является ссылочным типом, он D должен удовлетворять требованиям, MoveAssignable и назначение удалителя из rvalue типа D не должно вызывать исключения. В противном случае D - ссылочный тип; remove_reference_t<D> должен удовлетворять CopyAssignable требованиям, и назначение удалителя из lvalue типа D не должно вызывать исключения.
Effects: Передает право собственности от u к, *this как если бы при звонке с reset(u.release()) последующим get_deleter() = std::forward<D>(u.get_deleter()).
template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
Requires: Если E это не ссылочный тип, назначение удалителя из rvalue типа E должно быть правильно сформированным и не должно вызывать исключения. В противном случае E - это ссылочный тип, и назначение удалителя из lvalue типа E должно быть правильно сформированным и не должно вызывать исключения.
Effects: Передает право собственности от u к, *this как если бы при звонке с reset(u.release()) последующим get_deleter() = std::forward<E>(u.get_deleter()).
unique_ptr& operator=(nullptr_t) noexcept;
add_lvalue_reference_t<T> operator*() const;
pointer operator->() const noexcept;
pointer get() const noexcept;
deleter_type& get_deleter() noexcept;
const deleter_type& get_deleter() const noexcept;
explicit operator bool() const noexcept;
pointer release() noexcept;
void reset(pointer p = pointer()) noexcept;
Requires: Выражение get_deleter()(get()) должно быть правильно сформировано, иметь четко определенное поведение и не должно вызывать исключений.
Effects: Присваивается p сохраненному указателю, и затем, если и только если старое значение сохраненного указателя, old_pне было равно nullptr, вызывает get_deleter()(old_p). [ Note: Порядок этих операций важен, потому что вызов get_deleter() может уничтожить *this. ] — end note
Postconditions: get() == p. [ Note: Постусловие не выполняется, если вызов get_deleter() уничтожает, *this поскольку this->get() больше не является допустимым выражением. ] — end note
void swap(unique_ptr& u) noexcept;
namespace std { template <class T, class D> class unique_ptr<T[], D> { public: using pointer = see below; using element_type = T; using deleter_type = D; // [unique.ptr.runtime.ctor], constructors constexpr unique_ptr() noexcept; template <class U> explicit unique_ptr(U p) noexcept; template <class U> unique_ptr(U p, see below d) noexcept; template <class U> unique_ptr(U p, see below d) noexcept; unique_ptr(unique_ptr&& u) noexcept; template <class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept; // destructor ~unique_ptr(); // assignment unique_ptr& operator=(unique_ptr&& u) noexcept; template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; unique_ptr& operator=(nullptr_t) noexcept; // [unique.ptr.runtime.observers], observers T& operator[](size_t i) const; pointer get() const noexcept; deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept; explicit operator bool() const noexcept; // [unique.ptr.runtime.modifiers], modifiers pointer release() noexcept; template <class U> void reset(U p) noexcept; void reset(nullptr_t = nullptr) noexcept; void swap(unique_ptr& u) noexcept; // disable copy from lvalue unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; }; }
Специализация для типов массивов предоставляется с немного измененным интерфейсом.
Преобразования между различными типами, unique_ptr<T[], D> которые были бы запрещены для соответствующих типов указателей на массив, и преобразования в или из формunique_ptr, не являющихся массивами , создают плохо сформированную программу.
Указатели на типы, производные от T , отклоняются конструкторами и reset.
Наблюдатели так operator* и operator-> не предусмотрены.
Предусмотрен обозреватель индексации operator[] .
Будет звонить средство удаления по умолчанию delete[].
template <class U> explicit unique_ptr(U p) noexcept;
Этот конструктор ведет себя так же, как конструктор в основном шаблоне, который принимает единственный параметр типа, pointer за исключением того, что он дополнительно не должен участвовать в разрешении перегрузки, если только
U того же типа, что и pointer, или
pointer имеет тот же тип element_type*, U что и тип указателя V*, и V(*)[] может быть преобразован в element_type(*)[].
template <class U> unique_ptr(U p, see below d) noexcept;
template <class U> unique_ptr(U p, see below d) noexcept;
Эти конструкторы ведут себя так же, как конструкторы в основном шаблоне, которые принимают параметр типа pointer и второй параметр, за исключением того, что они не должны участвовать в разрешении перегрузки, если либо
U того же типа, что и pointer,
U есть nullptr_t, или
pointer имеет тот же тип element_type*, U что и тип указателя V*, и V(*)[] может быть преобразован в element_type(*)[].
template <class U, class E>
unique_ptr(unique_ptr<U, E>&& u) noexcept;
Этот конструктор ведет себя так же , как в первичном шаблоне, за исключением того, что она не будет участвовать в разрешении перегрузки , если все из следующих условий не выполняется, где UP находится unique_ptr<U, E>:
U - это тип массива, а
pointer того же типа element_type*, что и, и
UP::pointer того же типа UP::element_type*, что и, и
UP::element_type(*)[] конвертируется в element_type(*)[], и
либо D является ссылочным типом и E относится к тому же типу D, либо D не является ссылочным типом и E может неявно преобразовываться в D.
[ Note: Это заменяет спецификацию разрешения перегрузки основного шаблона ] — end note
template <class U, class E>
unique_ptr& operator=(unique_ptr<U, E>&& u)noexcept;
Этот оператор ведет себя так же , как в первичном шаблоне, за исключением того, что она не будет участвовать в разрешении перегрузки , если все из следующих условий не выполняется, где UP находится unique_ptr<U, E>:
U - это тип массива, а
pointer того же типа element_type*, что и, и
UP::pointer того же типа UP::element_type*, что и, и
UP::element_type(*)[] конвертируется в element_type(*)[], и
is_assignable_v<D&, E&&> есть true.
[ Note: Это заменяет спецификацию разрешения перегрузки основного шаблона ] — end note
T& operator[](size_t i) const;
void reset(nullptr_t p = nullptr) noexcept;
template <class U> void reset(U p) noexcept;
Эта функция ведет себя так же, как reset член основного шаблона, за исключением того, что она не должна участвовать в разрешении перегрузки, если либо
U того же типа, что и pointer, или
pointer имеет тот же тип element_type*, U что и тип указателя V*, и V(*)[] может быть преобразован в element_type(*)[].
template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если T она не является массивом.
template <class T> unique_ptr<T> make_unique(size_t n);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если только T это не массив с неизвестной границей.
template <class T, class... Args> unspecified make_unique(Args&&...) = delete;
template <class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_swappable_v<D> не true.
template <class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Requires: Пусть CT обозначают
common_type_t<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer>
Тогда специализация less<CT> должна быть a, function object type которая индуцирует a strict weak ordering для значений указателя.
Remarks: Если unique_ptr<T1, D1>::pointer не может быть неявно преобразован CT или unique_ptr<T2, D2>::pointer неявно преобразован в CT, программа имеет неправильный формат.
template <class T1, class D1, class T2, class D2>
bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T, class D>
bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D>
bool operator==(nullptr_t, const unique_ptr<T, D>& x) noexcept;
template <class T, class D>
bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D>
bool operator!=(nullptr_t, const unique_ptr<T, D>& x) noexcept;
template <class T, class D>
bool operator<(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator<(nullptr_t, const unique_ptr<T, D>& x);
Requires: Специализация less<unique_ptr<T, D>::pointer> должна быть a, function object type которая индуцирует a strict weak ordering для значений указателя.
Returns:
Первый шаблон функции возвращается
less<unique_ptr<T, D>::pointer>()(x.get(),
nullptr). Второй шаблон функции возвращается
less<unique_ptr<T, D>::pointer>()(nullptr, x.get()).
template <class T, class D>
bool operator>(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator>(nullptr_t, const unique_ptr<T, D>& x);
Returns: Первый шаблон функции возвращается nullptr < x. Второй шаблон функции возвращается x < nullptr.
template <class T, class D>
bool operator<=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator<=(nullptr_t, const unique_ptr<T, D>& x);
Returns: Первый шаблон функции возвращается !(nullptr < x). Второй шаблон функции возвращается !(x < nullptr).
template <class T, class D>
bool operator>=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator>=(nullptr_t, const unique_ptr<T, D>& x);
Returns: Первый шаблон функции возвращается !(x < nullptr). Второй шаблон функции возвращается !(nullptr < x).
namespace std { class bad_weak_ptr : public exception { public: bad_weak_ptr() noexcept; }; }
bad_weak_ptr() noexcept;
В weak_ptr шаблоне класса хранится слабая ссылка на объект, которым уже управляет shared_ptr. Для доступа к объекту a weak_ptr можно преобразовать в a shared_ptr с помощью функции-члена lock.
namespace std { template<class T> class weak_ptr { public: using element_type = T; // [util.smartptr.weak.const], constructors constexpr weak_ptr() noexcept; template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept; weak_ptr(const weak_ptr& r) noexcept; template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept; weak_ptr(weak_ptr&& r) noexcept; template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept; // [util.smartptr.weak.dest], destructor ~weak_ptr(); // [util.smartptr.weak.assign], assignment weak_ptr& operator=(const weak_ptr& r) noexcept; template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) noexcept; template<class Y> weak_ptr& operator=(const shared_ptr<Y>& r) noexcept; weak_ptr& operator=(weak_ptr&& r) noexcept; template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept; // [util.smartptr.weak.mod], modifiers void swap(weak_ptr& r) noexcept; void reset() noexcept; // [util.smartptr.weak.obs], observers long use_count() const noexcept; bool expired() const noexcept; shared_ptr<T> lock() const noexcept; template<class U> bool owner_before(const shared_ptr<U>& b) const; template<class U> bool owner_before(const weak_ptr<U>& b) const; }; template<class T> weak_ptr(shared_ptr<T>) -> weak_ptr<T>; // [util.smartptr.weak.spec], specialized algorithms template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept; }
Специализации weak_ptr должны быть CopyConstructible и CopyAssignable, позволяющие использовать их в стандартных контейнерах. Параметр шаблона T из weak_ptr может быть неполным типом.
constexpr weak_ptr() noexcept;
weak_ptr(const weak_ptr& r) noexcept;
template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept;
template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
Remarks: Второй и третий конструкторы не должны участвовать в разрешении перегрузки, если они Y* не совместимы с T*.
Effects: Если r пусто, создает пустой weak_ptr объект; в противном случае создает weak_ptr объект, который разделяет владение r и хранит копию указателя, хранящегося в r.
weak_ptr(weak_ptr&& r) noexcept;
template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept;
Remarks: Второй конструктор не должен участвовать в разрешении перегрузки, если он Y* не совместим с T*.
~weak_ptr();
weak_ptr& operator=(const weak_ptr& r) noexcept;
template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
template<class Y> weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
Remarks: Реализация может обеспечить эффекты (и подразумеваемые гарантии) разными способами, не создавая временного.
weak_ptr& operator=(weak_ptr&& r) noexcept;
template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
void swap(weak_ptr& r) noexcept;
void reset() noexcept;
long use_count() const noexcept;
Returns: 0 если *this пусто; в противном случае - количество shared_ptr экземпляров, с которыми совместно владеют *this.
bool expired() const noexcept;
shared_ptr<T> lock() const noexcept;
template<class U> bool owner_before(const shared_ptr<U>& b) const;
template<class U> bool owner_before(const weak_ptr<U>& b) const;
Returns: Неуказанное значение такое, что
x.owner_before(y) определяет строгий слабый порядок, как определено в [alg.sorting];
по отношению эквивалентности , определенное owner_before, !a.owner_before(b) && !b.owner_before(a)два shared_ptr или weak_ptr экземпляры эквивалентны тогда и только тогда , когда они имеют право собственности или являются пустыми.
template<class T>
void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
Шаблон класса owner_less позволяет смешанное сравнение общих и слабых указателей на основе владения.
namespace std {
template<class T = void> struct owner_less;
template<class T> struct owner_less<shared_ptr<T>> {
bool operator()(const shared_ptr<T>&, const shared_ptr<T>&) const noexcept;
bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept;
bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept;
};
template<class T> struct owner_less<weak_ptr<T>> {
bool operator()(const weak_ptr<T>&, const weak_ptr<T>&) const noexcept;
bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept;
bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept;
};
template<> struct owner_less<void> {
template<class T, class U>
bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept;
template<class T, class U>
bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept;
template<class T, class U>
bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept;
template<class T, class U>
bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept;
using is_transparent = unspecified;
};
}
operator()(x, y) вернусь x.owner_before(y). [ Note: Обратите внимание, что
operator() определяет строгий слабый порядок, как определено в [alg.sorting];
по отношению эквивалентности , определенное operator(), !operator()(a, b) && !operator()(b, a)два shared_ptr или weak_ptr экземпляры эквивалентны тогда и только тогда , когда они имеют право собственности или являются пустыми.
— end note ]
Класс T может наследовать от, enable_shared_from_this<T> чтобы наследовать shared_from_this функции-члены, которые получают shared_ptr экземпляр, указывающий на *this.
[ Example:
struct X: public enable_shared_from_this<X> { };
int main() {
shared_ptr<X> p(new X);
shared_ptr<X> q = p->shared_from_this();
assert(p == q);
assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership
}
— end example ]
namespace std {
template<class T> class enable_shared_from_this {
protected:
constexpr enable_shared_from_this() noexcept;
enable_shared_from_this(const enable_shared_from_this&) noexcept;
enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept;
~enable_shared_from_this();
public:
shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;
weak_ptr<T> weak_from_this() noexcept;
weak_ptr<T const> weak_from_this() const noexcept;
private:
mutable weak_ptr<T> weak_this; // exposition only
};
}
constexpr enable_shared_from_this() noexcept;
enable_shared_from_this(const enable_shared_from_this<T>&) noexcept;
enable_shared_from_this<T>& operator=(const enable_shared_from_this<T>&) noexcept;
shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;
weak_ptr<T> weak_from_this() noexcept;
weak_ptr<T const> weak_from_this() const noexcept;
template <class T, class D> struct hash<unique_ptr<T, D>>;
Позволить UP БЭ unique_ptr<T,D>, специализация hash<UP> включена ([unord.hash]) , если и только если hash<typename UP::pointer> включена. Если эта функция включена, для объекта p типа UP, hash<UP>()(p) должен оценить и то же значение , как hash<typename UP::pointer>()(p.get()). Функции-члены не гарантируются noexcept.
template <class T> struct hash<shared_ptr<T>>;