Namespaces
Variants

std::unique_ptr<T,Deleter>:: unique_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)
(Примечание: В данном фрагменте HTML отсутствует текстовое содержимое для перевода - присутствуют только HTML-теги и атрибуты, которые согласно инструкциям не подлежат переводу)
члены основного шаблона, unique_ptr<T>
constexpr unique_ptr ( ) noexcept ;
constexpr unique_ptr ( std:: nullptr_t ) noexcept ;
(1)
explicit unique_ptr ( pointer p ) noexcept ;
(2) (constexpr начиная с C++23)
unique_ptr ( pointer p, /* см. ниже */ d1 ) noexcept ;
(3) (constexpr начиная с C++23)
unique_ptr ( pointer p, /* см. ниже */ d2 ) noexcept ;
(4) (constexpr начиная с C++23)
unique_ptr ( unique_ptr && u ) noexcept ;
(5) (constexpr начиная с C++23)
template < class U, class E >
unique_ptr ( unique_ptr < U, E > && u ) noexcept ;
(6) (constexpr начиная с C++23)
unique_ptr ( const unique_ptr & ) = delete ;
(7)
template < class U >
unique_ptr ( std:: auto_ptr < U > && u ) noexcept ;
(8) (удалено в C++17)
члены специализации для массивов, unique_ptr<T[]>
constexpr unique_ptr ( ) noexcept ;
constexpr unique_ptr ( std:: nullptr_t ) noexcept ;
(1)
template < class U >
explicit unique_ptr ( U p ) noexcept ;
(2) (constexpr начиная с C++23)
template < class U >
unique_ptr ( U p, /* см. ниже */ d1 ) noexcept ;
(3) (constexpr начиная с C++23)
template < class U >
unique_ptr ( U p, /* см. ниже */ d2 ) noexcept ;
(4) (constexpr начиная с C++23)
unique_ptr ( unique_ptr && u ) noexcept ;
(5) (constexpr начиная с C++23)
template < class U, class E >
unique_ptr ( unique_ptr < U, E > && u ) noexcept ;
(6) (constexpr начиная с C++23)
unique_ptr ( const unique_ptr & ) = delete ;
(7)
1) Создает std::unique_ptr , который ничего не содержит. Инициализирует хранимый указатель и хранимый deleter значениями по умолчанию. Требует, чтобы Deleter был DefaultConstructible и чтобы конструкция не выбрасывала исключение. Эти перегрузки участвуют в разрешении перегрузки только если std:: is_default_constructible < Deleter > :: value равно true и Deleter не является типом указателя.
2) Создает std::unique_ptr , который владеет p , инициализируя сохраненный указатель значением p и инициализируя сохраненный удалитель значением по умолчанию. Требует, чтобы Deleter был DefaultConstructible и чтобы конструкция не выбрасывала исключение. Эта перегрузка участвует в разрешении перегрузки только если std:: is_default_constructible < Deleter > :: value равно true и Deleter не является типом указателя.

Этот конструктор не выбирается при выводе аргументов шаблона класса .

(начиная с C++17)
3,4) Создает объект std::unique_ptr , который владеет p , инициализируя сохраненный указатель значением p и инициализируя удалитель D следующим образом (зависит от того, является ли D ссылочным типом).
а) Если D является типом без ссылки A , тогда сигнатуры:
unique_ptr ( pointer p, const A & d ) noexcept ;
(1) (требует, чтобы Deleter был nothrow- CopyConstructible )
unique_ptr ( pointer p, A && d ) noexcept ;
(2) (требует, чтобы Deleter был nothrow- MoveConstructible )
б) Если D является типом lvalue-ссылки A & , тогда сигнатуры имеют вид:
unique_ptr ( pointer p, A & d ) noexcept ;
(1)
unique_ptr ( pointer p, A && d ) = delete ;
(2)
в) Если D является типом lvalue-ссылки const A & , тогда сигнатуры имеют вид:
unique_ptr ( pointer p, const A & d ) noexcept ;
(1)
unique_ptr ( pointer p, const A && d ) = delete ;
(2)
Во всех случаях удалитель инициализируется из std:: forward < decltype ( d ) > ( d ) . Эти перегрузки участвуют в разрешении перегрузки только если std:: is_constructible < D, decltype ( d ) > :: value равно true .

Эти два конструктора не выбираются выводом аргументов шаблона класса .

(since C++17)
2-4) В специализации для массивов ведут себя так же, как конструкторы, принимающие параметр-указатель в основном шаблоне, за исключением того, что они дополнительно не участвуют в разрешении перегрузки, если только одно из следующих условий не выполняется:
  • U имеет тот же тип, что и pointer , или
  • U является std::nullptr_t , или
  • pointer имеет тот же тип, что и element_type* , и U является некоторым типом указателя V* , таким что V(*)[] неявно преобразуется в element_type(*)[] .
5) Создает unique_ptr путем передачи владения из u в * this и сохраняет нулевой указатель в u . Этот конструктор участвует в разрешении перегрузки только если std:: is_move_constructible < Deleter > :: value равно true . Если Deleter не является ссылочным типом, требует, чтобы он был безысключительным MoveConstructible (если Deleter является ссылкой, get_deleter() и u.get_deleter() после перемещающего конструирования ссылаются на одно и то же значение).
6) Создает unique_ptr путем передачи владения от u к * this , где u создан с указанным удалителем ( E ). Зависит от того, является ли E ссылочным типом, следующим образом:
а) если E является ссылочным типом, этот удалитель копируется из u 's deleter (требуется, чтобы эта конструкция не выбрасывала исключений),
б) если E является типом без ссылки, этот удалитель перемещается из u 's deleter (требуется, чтобы эта конструкция не выбрасывала исключений).
Этот конструктор участвует в разрешении перегрузки только если все следующие условия выполняются:
а) unique_ptr < U, E > :: pointer неявно преобразуется в pointer ,
b) U не является массивным типом,
c) либо Deleter является ссылочным типом и E имеет тот же тип, что и Deleter , либо Deleter не является ссылочным типом и E неявно преобразуется в Deleter .
6) В специализации для массивов ведет себя так же, как в основной шаблонной версии, за исключением того, что будет участвовать в разрешении перегрузки только при выполнении всех следующих условий:
  • U является типом массива,
  • pointer имеет тот же тип, что и element_type* ,
  • unique_ptr < U,E > :: pointer имеет тот же тип, что и unique_ptr < U,E > :: element_type * ,
  • unique_ptr < U,E > :: element_type ( * ) [ ] преобразуется в element_type(*)[] ,
  • либо Deleter является ссылочным типом и E имеет тот же тип, что и Deleter , либо Deleter не является ссылочным типом и E неявно преобразуется в Deleter .
7) Конструктор копирования явно удален.
8) Создает unique_ptr , в котором сохраненный указатель инициализируется с помощью u.release() , а сохраненный удалитель инициализируется значением по умолчанию. Этот конструктор участвует в разрешении перегрузки только если U* неявно преобразуется в T* и Deleter имеет тот же тип, что и std:: default_delete < T > .

Содержание

Параметры

p - указатель на управляемый объект
d1, d2 - удалитель для уничтожения объекта
u - другой умный указатель для получения владения

Примечания

Вместо использования перегрузки (2) вместе с new, часто лучше использовать std::make_unique<T> .

(since C++14)

std:: unique_ptr < Derived > неявно преобразуется в std:: unique_ptr < Base > через перегрузку (6) (поскольку и управляемый указатель, и std::default_delete неявно преобразуемы).

Поскольку конструктор по умолчанию является constexpr , статические unique_ptr инициализируются как часть статической нелокальной инициализации , до начала любой динамической нелокальной инициализации. Это делает безопасным использование unique_ptr в конструкторе любого статического объекта.

Нет вывода аргументов шаблона класса из указателя, поскольку невозможно различить указатель, полученный из массивной и не-массивной форм new .

(since C++17)

Пример

#include <iostream>
#include <memory>
struct Foo // объект для управления
{
    Foo() { std::cout << "Foo конструктор\n"; }
    Foo(const Foo&) { std::cout << "Foo конструктор копирования\n"; }
    Foo(Foo&&) { std::cout << "Foo move ctor\n"; }
    ~Foo() { std::cout << "~Foo деструктор\n"; }
};
struct D // deleter
{
    D() {};
    D(const D&) { std::cout << "D конструктор копирования\n"; }
    D(D&) { std::cout << "D неконстантный конструктор копирования\n"; }
    D(D&&) { std::cout << "D конструктор перемещения \n"; }
    void operator()(Foo* p) const
    {
        std::cout << "D удаляет Foo\n";
        delete p;
    };
};
int main()
{
    std::cout << "Пример конструктора(1)...\n";
    std::unique_ptr<Foo> up1; // up1 пуст
    std::unique_ptr<Foo> up1b(nullptr); // up1b пуст
    std::cout << "Пример конструктора(2)...\n";
    {
        std::unique_ptr<Foo> up2(new Foo); //up2 теперь владеет Foo
    } // Foo удален
    std::cout << "Пример конструктора(3)...\n";
    D d;
    {   // тип deleter не является ссылкой
        std::unique_ptr<Foo, D> up3(new Foo, d); // удалитель скопирован
    }
    {   // тип deleter является ссылкой
        std::unique_ptr<Foo, D&> up3b(new Foo, d); // up3b содержит ссылку на d
    }
    std::cout << "Пример конструктора(4)...\n";
    {   // deleter не является ссылкой
        std::unique_ptr<Foo, D> up4(new Foo, D()); // deleter moved
    }
    std::cout << "Пример конструктора(5)...\n";
    {
        std::unique_ptr<Foo> up5a(new Foo);
        std::unique_ptr<Foo> up5b(std::move(up5a)); // передача владения
    }
    std::cout << "Пример конструктора(6)...\n";
    {
        std::unique_ptr<Foo, D> up6a(new Foo, d); // D копируется
        std::unique_ptr<Foo, D> up6b(std::move(up6a)); // D перемещён
        std::unique_ptr<Foo, D&> up6c(new Foo, d); // D является ссылкой
        std::unique_ptr<Foo, D> up6d(std::move(up6c)); // D копируется
    }
#if (__cplusplus < 201703L)
    std::cout << "Пример конструктора(7)...\n";
    {
        std::auto_ptr<Foo> up7a(new Foo);
        std::unique_ptr<Foo> up7b(std::move(up7a)); // передача владения
    }
#endif
    std::cout << "Пример конструктора массива...\n";
    {
        std::unique_ptr<Foo[]> up(new Foo[3]);
    } // три объекта Foo удалены
}

Вывод:

Пример конструктора(1)...
Пример конструктора(2)...
Foo ctor
~Foo dtor
Пример конструктора(3)...
Foo ctor
D copy ctor
D is deleting a Foo
~Foo dtor
Foo ctor
D is deleting a Foo
~Foo dtor
Пример конструктора(4)...
Foo ctor
D move ctor
D is deleting a Foo
~Foo dtor
Пример конструктора(5)...
Foo ctor
~Foo dtor
Пример конструктора(6)...
Foo ctor
D copy ctor
D move ctor
Foo ctor
D non-const copy ctor
D is deleting a Foo
~Foo dtor
D is deleting a Foo
~Foo dtor
Пример конструктора(7)...
Foo ctor
~Foo dtor
Пример конструктора массива...
Foo ctor
Foo ctor
Foo ctor
~Foo dtor
~Foo dtor
~Foo dtor

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применяется к Поведение в опубликованной версии Корректное поведение
LWG 2118 C++11 Конструкторы unique_ptr<T[]> отвергали квалификационные преобразования. Принимать.
LWG 2520 C++11 unique_ptr<T[]> случайно стал неконструируемым из nullptr_t . Сделать конструируемым.
LWG 2801 C++11 Конструктор по умолчанию не был ограничен. Ограничен.
LWG 2899 C++11 Перемещающий конструктор не был ограничен. Ограничен.
LWG 2905 C++11 Ограничение на конструктор из указателя и удалителя было неверным. Исправлено.
LWG 2944 C++11 Некоторые предусловия были случайно удалены LWG 2905 Восстановлены.