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)
Mitglieder der primären Template, unique_ptr<T>
constexpr unique_ptr ( ) noexcept ;
constexpr unique_ptr ( std:: nullptr_t ) noexcept ;
(1)
explicit unique_ptr ( pointer p ) noexcept ;
(2) (constexpr seit C++23)
unique_ptr ( pointer p, /* siehe unten */ d1 ) noexcept ;
(3) (constexpr seit C++23)
unique_ptr ( pointer p, /* siehe unten */ d2 ) noexcept ;
(4) (constexpr seit C++23)
unique_ptr ( unique_ptr && u ) noexcept ;
(5) (constexpr seit C++23)
template < class U, class E >
unique_ptr ( unique_ptr < U, E > && u ) noexcept ;
(6) (constexpr seit C++23)
unique_ptr ( const unique_ptr & ) = delete ;
(7)
template < class U >
unique_ptr ( std:: auto_ptr < U > && u ) noexcept ;
(8) (entfernt in C++17)
Mitglieder der Spezialisierung für Arrays, 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 seit C++23)
template < class U >
unique_ptr ( U p, /* siehe unten */ d1 ) noexcept ;
(3) (constexpr seit C++23)
template < class U >
unique_ptr ( U p, /* siehe unten */ d2 ) noexcept ;
(4) (constexpr seit C++23)
unique_ptr ( unique_ptr && u ) noexcept ;
(5) (constexpr seit C++23)
template < class U, class E >
unique_ptr ( unique_ptr < U, E > && u ) noexcept ;
(6) (constexpr seit C++23)
unique_ptr ( const unique_ptr & ) = delete ;
(7)
1) Konstruiert einen std::unique_ptr der nichts besitzt. Wertinitialisiert den gespeicherten Zeiger und den gespeicherten Deleter. Erfordert, dass Deleter DefaultConstructible ist und dass die Konstruktion keine Ausnahme wirft. Diese Überladungen nehmen nur dann an der Überladungsauflösung teil, wenn std:: is_default_constructible < Deleter > :: value true ist und Deleter kein Zeigertyp ist.
2) Konstruiert einen std::unique_ptr , der p besitzt, initialisiert den gespeicherten Zeiger mit p und wertinitialisiert den gespeicherten Deleter. Erfordert, dass Deleter DefaultConstructible ist und dass die Konstruktion keine Ausnahme auslöst. Diese Überladung nimmt nur dann an der Überladungsauflösung teil, wenn std:: is_default_constructible < Deleter > :: value true ist und Deleter kein Zeigertyp ist.

Dieser Konstruktor wird nicht durch Class Template Argument Deduction ausgewählt.

(seit C++17)
3,4) Konstruiert ein std::unique_ptr -Objekt, das p besitzt, initialisiert den gespeicherten Zeiger mit p und initialisiert einen Deleter D wie folgt (hängt davon ab, ob D ein Referenztyp ist).
a) Wenn D ein Nicht-Referenztyp A ist, dann sind die Signaturen:
unique_ptr ( pointer p, const A & d ) noexcept ;
(1) (erfordert, dass Deleter nothrow- CopyConstructible ist)
unique_ptr ( pointer p, A && d ) noexcept ;
(2) (erfordert, dass Deleter nothrow- MoveConstructible ist)
b) Wenn D ein Lvalue-Referenztyp A & ist, dann lauten die Signaturen:
unique_ptr ( pointer p, A & d ) noexcept ;
(1)
unique_ptr ( pointer p, A && d ) = delete ;
(2)
c) Wenn D ein Lvalue-Referenztyp const A & ist, dann lauten die Signaturen:
unique_ptr ( pointer p, const A & d ) noexcept ;
(1)
unique_ptr ( pointer p, const A && d ) = delete ;
(2)
In allen Fällen wird der Deleter initialisiert von std:: forward < decltype ( d ) > ( d ) . Diese Überladungen nehmen nur dann an der Überladungsauflösung teil, wenn std:: is_constructible < D, decltype ( d ) > :: value gleich true ist.

Diese beiden Konstruktoren werden nicht durch Klassen-Template-Argument-Deduktion ausgewählt.

(seit C++17)
2-4) In der Spezialisierung für Arrays verhalten sich diese wie die Konstruktoren mit einem Zeigerparameter in der primären Template-Definition, mit der zusätzlichen Einschränkung, dass sie nicht an der Überladungsauflösung teilnehmen, es sei denn, eine der folgenden Bedingungen ist erfüllt:
  • U ist der gleiche Typ wie pointer , oder
  • U ist std::nullptr_t , oder
  • pointer ist der gleiche Typ wie element_type* und U ist ein Zeigertyp V* , sodass V(*)[] implizit konvertierbar zu element_type(*)[] ist.
5) Konstruiert einen unique_ptr durch Übertragung des Besitzes von u an * this und speichert den Nullzeiger in u . Dieser Konstruktor nimmt nur an der Überladungsauflösung teil, wenn std:: is_move_constructible < Deleter > :: value gleich true ist. Wenn Deleter kein Referenztyp ist, erfordert dies, dass es nothrow- MoveConstructible ist (wenn Deleter eine Referenz ist, verweisen get_deleter() und u.get_deleter() nach der Move-Konstruktion auf denselben Wert).
6) Konstruiert einen unique_ptr durch Übertragung des Besitzes von u an * this , wobei u mit einem spezifizierten Deleter ( E ) konstruiert wird. Es hängt davon ab, ob E ein Referenztyp ist, wie folgt:
a) if E ein Referenztyp ist, wird dieser Deleter aus u 's Deleter kopierkonstruiert (erfordert, dass diese Konstruktion keine Ausnahme wirft),
b) wenn E ein Nicht-Referenztyp ist, wird dieser Deleter aus u 's Deleter move-konstruiert (erfordert, dass diese Konstruktion keine Ausnahme wirft).
Dieser Konstruktor nimmt nur dann an der Überladungsauflösung teil, wenn alle folgenden Bedingungen zutreffen:
a) unique_ptr < U, E > :: pointer ist implizit konvertierbar zu pointer ,
b) U ist kein Array-Typ,
c) entweder ist Deleter ein Referenztyp und E ist vom gleichen Typ wie Deleter , oder Deleter ist kein Referenztyp und E ist implizit konvertierbar zu Deleter .
6) In der Spezialisierung für Arrays verhält es sich gleich wie in der primären Vorlage, außer dass es nur an der Überladungsauflösung teilnimmt, wenn alle der folgenden Bedingungen erfüllt sind:
  • U ist ein Array-Typ,
  • pointer ist vom gleichen Typ wie element_type* ,
  • unique_ptr < U,E > :: pointer ist vom gleichen Typ wie unique_ptr < U,E > :: element_type * ,
  • unique_ptr < U,E > :: element_type ( * ) [ ] ist konvertierbar zu element_type(*)[] ,
  • entweder Deleter ist ein Referenztyp und E ist vom gleichen Typ wie Deleter , oder Deleter ist kein Referenztyp und E ist implizit konvertierbar zu Deleter .
7) Copy-Konstruktor ist explizit gelöscht.
8) Konstruiert einen unique_ptr , bei dem der gespeicherte Zeiger mit u.release() initialisiert wird und der gespeicherte Deleter wertinitialisiert ist. Dieser Konstruktor nimmt nur an der Überladungsauflösung teil, wenn U* implizit in T* konvertierbar ist und Deleter denselben Typ wie std:: default_delete < T > besitzt.

Inhaltsverzeichnis

Parameter

p - ein Zeiger auf ein zu verwaltendes Objekt
d1, d2 - ein Deleter zur Zerstörung des Objekts
u - ein weiterer Smart Pointer, von dem der Besitz übernommen wird

Hinweise

Anstatt die Überladung (2) zusammen mit new zu verwenden, ist es oft besser, std::make_unique<T> zu verwenden.

(since C++14)

std:: unique_ptr < Derived > ist implizit konvertierbar zu std:: unique_ptr < Base > durch Überladung (6) (da sowohl der verwaltete Zeiger als auch std::default_delete implizit konvertierbar sind).

Da der Standardkonstruktor constexpr ist, werden statische unique_ptrs als Teil der statischen Nicht-Lokalen Initialisierung initialisiert, bevor jegliche dynamische Nicht-Lokale Initialisierung beginnt. Dies macht es sicher, einen unique_ptr im Konstruktor eines beliebigen statischen Objekts zu verwenden.

Es gibt keine Klassentemplate-Argumentableitung von Zeigertypen, da es unmöglich ist, zwischen einem Zeiger aus Array- und Nicht-Array-Formen von new zu unterscheiden.

(seit C++17)

Beispiel

#include <iostream>
#include <memory>
struct Foo // Objekt zur Verwaltung
{
    Foo() { std::cout << "Foo Konstruktor\n"; }
    Foo(const Foo&) { std::cout << "Foo Kopierkonstruktor\n"; }
    Foo(Foo&&) { std::cout << "Foo Move-Konstruktor\n"; }
    ~Foo() { std::cout << "~Foo Destruktor\n"; }
};
struct D // Deleter
{
    D() {};
    D(const D&) { std::cout << "D Kopierkonstruktor\n"; }
    D(D&) { std::cout << "D nicht-konstante Kopierkonstruktor\n"; }
    D(D&&) { std::cout << "D Move-Konstruktor \n"; }
    void operator()(Foo* p) const
    {
        std::cout << "D löscht ein Foo\n";
        delete p;
    };
};
int main()
{
    std::cout << "Beispiel Konstruktor(1)...\n";
    std::unique_ptr<Foo> up1; // up1 ist leer
    std::unique_ptr<Foo> up1b(nullptr); // up1b ist leer
    std::cout << "Beispiel Konstruktor(2)...\n";
    {
        std::unique_ptr<Foo> up2(new Foo); //up2 besitzt jetzt ein Foo
    } // Foo gelöscht
    std::cout << "Beispiel Konstruktor(3)...\n";
    D d;
    {   // Deleter-Typ ist keine Referenz
        std::unique_ptr<Foo, D> up3(new Foo, d); // Deleter kopiert
    }
    {   // Deleter-Typ ist eine Referenz
        std::unique_ptr<Foo, D&> up3b(new Foo, d); // up3b enthält eine Referenz auf d
    }
    std::cout << "Beispiel Konstruktor(4)...\n";
    {   // deleter ist keine Referenz
        std::unique_ptr<Foo, D> up4(new Foo, D()); // deleter moved
    }
    std::cout << "Beispiel Konstruktor(5)...\n";
    {
        std::unique_ptr<Foo> up5a(new Foo);
        std::unique_ptr<Foo> up5b(std::move(up5a)); // Eigentumsübertragung
    }
    std::cout << "Beispiel Konstruktor(6)...\n";
    {
        std::unique_ptr<Foo, D> up6a(new Foo, d); // D wird kopiert
        std::unique_ptr<Foo, D> up6b(std::move(up6a)); // D wird verschoben
        std::unique_ptr<Foo, D&> up6c(new Foo, d); // D ist eine Referenz
        std::unique_ptr<Foo, D> up6d(std::move(up6c)); // D wird kopiert
    }
#if (__cplusplus < 201703L)
    std::cout << "Beispiel Konstruktor(7)...\n";
    {
        std::auto_ptr<Foo> up7a(new Foo);
        std::unique_ptr<Foo> up7b(std::move(up7a)); // Eigentumsübertragung
    }
#endif
    std::cout << "Beispiel Array-Konstruktor...\n";
    {
        std::unique_ptr<Foo[]> up(new Foo[3]);
    } // drei Foo-Objekte gelöscht
}

Ausgabe:

Beispiel Konstruktor(1)...
Beispiel Konstruktor(2)...
Foo ctor
~Foo dtor
Beispiel Konstruktor(3)...
Foo ctor
D copy ctor
D löscht ein Foo
~Foo dtor
Foo ctor
D löscht ein Foo
~Foo dtor
Beispiel Konstruktor(4)...
Foo ctor
D move ctor
D löscht ein Foo
~Foo dtor
Beispiel Konstruktor(5)...
Foo ctor
~Foo dtor
Beispiel Konstruktor(6)...
Foo ctor
D copy ctor
D move ctor
Foo ctor
D non-const copy ctor
D löscht ein Foo
~Foo dtor
D löscht ein Foo
~Foo dtor
Beispiel Konstruktor(7)...
Foo ctor
~Foo dtor
Beispiel Array-Konstruktor...
Foo ctor
Foo ctor
Foo ctor
~Foo dtor
~Foo dtor
~Foo dtor

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
LWG 2118 C++11 Konstruktoren von unique_ptr<T[]> lehnten Qualifikationskonvertierungen ab. Akzeptiert.
LWG 2520 C++11 unique_ptr<T[]> wurde versehentlich nicht-konstruierbar von nullptr_t gemacht. Konstruierbar gemacht.
LWG 2801 C++11 Der Standardkonstruktor war nicht eingeschränkt. Eingeschränkt.
LWG 2899 C++11 Der Move-Konstruktor war nicht eingeschränkt. Eingeschränkt.
LWG 2905 C++11 Einschränkung des Konstruktors von einem Zeiger und einem Deleter war falsch. Korrigiert.
LWG 2944 C++11 Einige Vorbedingungen wurden versehentlich durch LWG 2905 entfernt Wiederhergestellt.