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)
membres du modèle principal, unique_ptr<T>
constexpr unique_ptr ( ) noexcept ;
constexpr unique_ptr ( std:: nullptr_t ) noexcept ;
(1)
explicit unique_ptr ( pointer p ) noexcept ;
(2) (constexpr depuis C++23)
unique_ptr ( pointer p, /* voir ci-dessous */ d1 ) noexcept ;
(3) (constexpr depuis C++23)
unique_ptr ( pointer p, /* voir ci-dessous */ d2 ) noexcept ;
(4) (constexpr depuis C++23)
unique_ptr ( unique_ptr && u ) noexcept ;
(5) (constexpr depuis C++23)
template < class U, class E >
unique_ptr ( unique_ptr < U, E > && u ) noexcept ;
(6) (constexpr depuis C++23)
unique_ptr ( const unique_ptr & ) = delete ;
(7)
template < class U >
unique_ptr ( std:: auto_ptr < U > && u ) noexcept ;
(8) (supprimé en C++17)
membres de la spécialisation pour les tableaux, 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 depuis C++23)
template < class U >
unique_ptr ( U p, /* voir ci-dessous */ d1 ) noexcept ;
(3) (constexpr depuis C++23)
template < class U >
unique_ptr ( U p, /* voir ci-dessous */ d2 ) noexcept ;
(4) (constexpr depuis C++23)
unique_ptr ( unique_ptr && u ) noexcept ;
(5) (constexpr depuis C++23)
template < class U, class E >
unique_ptr ( unique_ptr < U, E > && u ) noexcept ;
(6) (constexpr depuis C++23)
unique_ptr ( const unique_ptr & ) = delete ;
(7)
1) Construit un std::unique_ptr qui ne possède rien. Initialise par défaut le pointeur stocké et le suppresseur stocké. Requiert que Deleter soit DefaultConstructible et que la construction ne lève pas d'exception. Ces surcharges participent à la résolution de surcharge seulement si std:: is_default_constructible < Deleter > :: value est true et Deleter n'est pas un type pointeur.
2) Construit un std::unique_ptr qui possède p , initialisant le pointeur stocké avec p et initialisant par défaut le suppresseur stocké. Requiert que Deleter soit DefaultConstructible et que la construction ne lève pas d'exception. Cette surcharge participe à la résolution de surcharge seulement si std:: is_default_constructible < Deleter > :: value est true et Deleter n'est pas un type pointeur.

Ce constructeur n'est pas sélectionné par la déduction d'arguments de modèle de classe .

(depuis C++17)
3,4) Construit un objet std::unique_ptr qui possède p , initialisant le pointeur stocké avec p et initialisant un suppresseur D comme ci-dessous (dépend si D est un type référence).
a) Si D est un type non-référence A , alors les signatures sont :
unique_ptr ( pointer p, const A & d ) noexcept ;
(1) (requiert que Deleter soit nothrow- CopyConstructible )
unique_ptr ( pointer p, A && d ) noexcept ;
(2) (requiert que Deleter soit nothrow- MoveConstructible )
b) Si D est un type de référence lvalue A & , alors les signatures sont :
unique_ptr ( pointer p, A & d ) noexcept ;
(1)
unique_ptr ( pointer p, A && d ) = delete ;
(2)
c) Si D est un type référence lvalue const A & , alors les signatures sont :
unique_ptr ( pointer p, const A & d ) noexcept ;
(1)
unique_ptr ( pointer p, const A && d ) = delete ;
(2)
Dans tous les cas, le deleter est initialisé à partir de std:: forward < decltype ( d ) < ( d ) . Ces surcharges participent à la résolution de surcharge seulement si std:: is_constructible < D, decltype ( d ) > :: value est true .

Ces deux constructeurs ne sont pas sélectionnés par la déduction d'arguments de modèle de classe .

(depuis C++17)
2-4) Dans la spécialisation pour les tableaux, ils se comportent de la même manière que les constructeurs qui prennent un paramètre pointeur dans le modèle primaire, sauf qu'ils ne participent pas en outre à la résolution de surcharge sauf si l'une des conditions suivantes est vraie :
  • U est du même type que pointer , ou
  • U est std::nullptr_t , ou
  • pointer est du même type que element_type* et U est un type pointeur V* tel que V(*)[] est implicitement convertible en element_type(*)[] .
5) Construit un unique_ptr en transférant la propriété de u vers * this et stocke le pointeur nul dans u . Ce constructeur ne participe à la résolution de surcharge que si std:: is_move_constructible < Deleter > :: value est true . Si Deleter n'est pas un type référence, nécessite qu'il soit non-lançant- MoveConstructible (si Deleter est une référence, get_deleter() et u.get_deleter() après la construction par déplacement référencent la même valeur).
6) Construit un unique_ptr en transférant la propriété de u vers * this , où u est construit avec un suppresseur spécifié ( E ). Cela dépend si E est un type référence, comme suit :
a) si E est un type référence, ce suppresseur est copié-construit à partir du suppresseur de u (nécessite que cette construction ne lève pas d'exception),
b) si E est un type non-référence, ce suppresseur est construit par déplacement à partir du suppresseur de u (nécessite que cette construction ne lève pas d'exception).
Ce constructeur ne participe à la résolution de surcharge que si toutes les conditions suivantes sont vraies :
a) unique_ptr < U, E > :: pointer est implicitement convertible en pointer ,
b) U n'est pas un type tableau,
c) soit Deleter est un type référence et E est du même type que Deleter , soit Deleter n'est pas un type référence et E est implicitement convertible en Deleter .
6) Dans la spécialisation pour les tableaux, le comportement est le même que dans le modèle primaire, sauf qu'elle ne participera à la résolution de surcharge que si toutes les conditions suivantes sont vraies :
  • U est un type tableau,
  • pointer est du même type que element_type* ,
  • unique_ptr < U,E > :: pointer est du même type que unique_ptr < U,E > :: element_type * ,
  • unique_ptr < U,E > :: element_type ( * ) [ ] est convertible en element_type(*)[] ,
  • soit Deleter est un type référence et E est du même type que Deleter , soit Deleter n'est pas un type référence et E est implicitement convertible en Deleter .
7) Le constructeur de copie est explicitement supprimé.
8) Construit un unique_ptr où le pointeur stocké est initialisé avec u.release() et le suppresseur stocké est initialisé par valeur. Ce constructeur ne participe à la résolution de surcharge que si U* est implicitement convertible en T* et Deleter est du même type que std:: default_delete < T > .

Table des matières

Paramètres

p - un pointeur vers un objet à gérer
d1, d2 - un suppresseur à utiliser pour détruire l'objet
u - un autre pointeur intelligent dont il faut acquérir la propriété

Notes

Au lieu d'utiliser la surcharge (2) avec new, il est souvent préférable d'utiliser std::make_unique<T> .

(depuis C++14)

std:: unique_ptr < Derived > est implicitement convertible en std:: unique_ptr < Base > via la surcharge (6) (car le pointeur géré et std::default_delete sont tous deux implicitement convertibles).

Parce que le constructeur par défaut est constexpr , les unique_ptrs statiques sont initialisés dans le cadre de l'initialisation statique non locale , avant que toute initialisation dynamique non locale ne commence. Cela rend sûr d'utiliser un unique_ptr dans le constructeur de tout objet statique.

Il n'y a pas de déduction d'arguments de modèle de classe à partir d'un type pointeur car il est impossible de distinguer un pointeur obtenu à partir des formes tableau et non-tableau de new .

(depuis C++17)

Exemple

#include <iostream>
#include <memory>
struct Foo // objet à gérer
{
    Foo() { std::cout << "Constructeur Foo\n"; }
    Foo(const Foo&) { std::cout << "Foo constructeur de copie\n"; }
    Foo(Foo&&) { std::cout << "Constructeur de déplacement Foo\n"; }
    ~Foo() { std::cout << "~Foo dtor\n"; }
};
struct D // deleter
{
    D() {};
    D(const D&) { std::cout << "Constructeur de copie D\n"; }
    D(D&) { std::cout << "D constructeur de copie non-const\n"; }
    D(D&&) { std::cout << "D constructeur de déplacement \n"; }
    void operator()(Foo* p) const
    {
        std::cout << "D supprime un Foo\n";
        delete p;
    };
};
int main()
{
    std::cout << "Exemple de constructeur(1)...\n";
    std::unique_ptr<Foo> up1; // up1 est vide
    std::unique_ptr<Foo> up1b(nullptr); // up1b est vide
    std::cout << "Exemple de constructeur(2)...\n";
    {
        std::unique_ptr<Foo> up2(new Foo); //up2 possède maintenant un Foo
    } // Foo supprimé
    std::cout << "Exemple de constructeur(3)...\n";
    D d;
    {   // le type deleter n'est pas une référence
        std::unique_ptr<Foo, D> up3(new Foo, d); // suppresseur copié
    }
    {   // le type deleter est une référence
        std::unique_ptr<Foo, D&> up3b(new Foo, d); // up3b contient une référence à d
    }
    std::cout << "Exemple de constructeur(4)...\n";
    {   // deleter n'est pas une référence
        std::unique_ptr<Foo, D> up4(new Foo, D()); // deleter déplacé
    }
    std::cout << "Exemple de constructeur(5)...\n";
    {
        std::unique_ptr<Foo> up5a(new Foo);
        std::unique_ptr<Foo> up5b(std::move(up5a)); // transfert de propriété
    }
    std::cout << "Exemple de constructeur(6)...\n";
    {
        std::unique_ptr<Foo, D> up6a(new Foo, d); // D est copié
        std::unique_ptr<Foo, D> up6b(std::move(up6a)); // D est déplacé
        std::unique_ptr<Foo, D&> up6c(new Foo, d); // D est une référence
        std::unique_ptr<Foo, D> up6d(std::move(up6c)); // D est copié
    }
#if (__cplusplus < 201703L)
    std::cout << "Exemple de constructeur(7)...\n";
    {
        std::auto_ptr<Foo> up7a(new Foo);
        std::unique_ptr<Foo> up7b(std::move(up7a)); // transfert de propriété
    }
#endif
    std::cout << "Constructeur de tableau d'exemple...\n";
    {
        std::unique_ptr<Foo[]> up(new Foo[3]);
    } // trois objets Foo supprimés
}

Sortie :

Exemple constructeur(1)...
Exemple constructeur(2)...
Foo ctor
~Foo dtor
Exemple constructeur(3)...
Foo ctor
D copy ctor
D supprime un Foo
~Foo dtor
Foo ctor
D supprime un Foo
~Foo dtor
Exemple constructeur(4)...
Foo ctor
D move ctor
D supprime un Foo
~Foo dtor
Exemple constructeur(5)...
Foo ctor
~Foo dtor
Exemple constructeur(6)...
Foo ctor
D copy ctor
D move ctor
Foo ctor
D non-const copy ctor
D supprime un Foo
~Foo dtor
D supprime un Foo
~Foo dtor
Exemple constructeur(7)...
Foo ctor
~Foo dtor
Exemple constructeur de tableau...
Foo ctor
Foo ctor
Foo ctor
~Foo dtor
~Foo dtor
~Foo dtor

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement corrigé
LWG 2118 C++11 Les constructeurs de unique_ptr<T[]> rejetaient les conversions de qualification. Acceptées.
LWG 2520 C++11 unique_ptr<T[]> était accidentellement rendu non constructible à partir de nullptr_t . Rendu constructible.
LWG 2801 C++11 Le constructeur par défaut n'était pas contraint. Contraint.
LWG 2899 C++11 Le constructeur de déplacement n'était pas contraint. Contraint.
LWG 2905 C++11 La contrainte sur le constructeur à partir d'un pointeur et d'un deleter était incorrecte. Corrigée.
LWG 2944 C++11 Certains prérequis ont été accidentellement supprimés par LWG 2905 Restaurés.