Namespaces
Variants

std::shared_ptr<T>:: shared_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)
(Anmerkung: Der bereitgestellte HTML-Code enthält keinen übersetzbaren Text, da alle Tags und Attribute gemäß den Anweisungen unverändert bleiben sollen und die Tabellenzellen leer sind.)
constexpr shared_ptr ( ) noexcept ;
(1)
constexpr shared_ptr ( std:: nullptr_t ) noexcept ;
(2)
template < class Y >
explicit shared_ptr ( Y * ptr ) ;
(3)
template < class Y, class Deleter >
shared_ptr ( Y * ptr, Deleter d ) ;
(4)
template < class Deleter >
shared_ptr ( std:: nullptr_t ptr, Deleter d ) ;
(5)
template < class Y, class Deleter, class Alloc >
shared_ptr ( Y * ptr, Deleter d, Alloc alloc ) ;
(6)
template < class Deleter, class Alloc >
shared_ptr ( std:: nullptr_t ptr, Deleter d, Alloc alloc ) ;
(7)
template < class Y >
shared_ptr ( const shared_ptr < Y > & r, element_type * ptr ) noexcept ;
(8)
template < class Y >
shared_ptr ( shared_ptr < Y > && r, element_type * ptr ) noexcept ;
(8) (seit C++20)
shared_ptr ( const shared_ptr & r ) noexcept ;
(9)
template < class Y >
shared_ptr ( const shared_ptr < Y > & r ) noexcept ;
(9)
shared_ptr ( shared_ptr && r ) noexcept ;
(10)
template < class Y >
shared_ptr ( shared_ptr < Y > && r ) noexcept ;
(10)
template < class Y >
explicit shared_ptr ( const std:: weak_ptr < Y > & r ) ;
(11)
template < class Y >
shared_ptr ( std:: auto_ptr < Y > && r ) ;
(12) (entfernt in C++17)
template < class Y, class Deleter >
shared_ptr ( std:: unique_ptr < Y, Deleter > && r ) ;
(13)

Konstruiert einen neuen shared_ptr aus verschiedenen Zeigertypen, die auf ein zu verwaltendes Objekt verweisen.

Für die Zwecke der nachfolgenden Beschreibung wird ein Zeigertyp Y* als kompatibel mit einem Zeigertyp T* bezeichnet, wenn entweder Y* in T* konvertierbar ist oder Y der Array-Typ U[N] ist und T U cv [] ist (wobei cv eine Menge von CV-Qualifizierern darstellt).

(since C++17)
1,2) Konstruiert einen shared_ptr ohne verwaltetes Objekt, d.h. einen leeren shared_ptr .
3-7) Konstruiert einen shared_ptr mit ptr als Zeiger auf das verwaltete Objekt.

Für (3,4,6) muss Y* konvertierbar zu T* sein.

(bis C++17)

Falls T ein Array-Typ U[N] ist, nehmen (3,4,6) nicht an der Überladungsauflösung teil, wenn Y(*)[N] ein ungültiger Typ ist oder nicht zu T* konvertierbar ist. Falls T ein Array-Typ U[] ist, nehmen (3,4,6) nicht an der Überladungsauflösung teil, wenn Y(*)[] ein ungültiger Typ ist oder nicht zu T* konvertierbar ist. Andernfalls nehmen (3,4,6) nicht an der Überladungsauflösung teil, wenn Y* nicht zu T* konvertierbar ist.

(seit C++17)
Zusätzlich:
3) Verwendet den delete-expression delete ptr falls T kein Array-Typ ist; delete [ ] ptr falls T ein Array-Typ ist (seit C++17) als Deleter. Y muss ein vollständiger Typ sein. Der delete-Ausdruck muss wohlgeformt sein, wohldefiniertes Verhalten aufweisen und keine Ausnahmen werfen. Dieser Konstruktor nimmt zusätzlich nicht an der Überladungsauflösung teil, falls der delete-Ausdruck nicht wohlgeformt ist. (seit C++17)
4,5) Verwendet den angegebenen Deleter d als Deleter. Der Ausdruck d ( ptr ) muss wohlgeformt sein, wohldefiniertes Verhalten aufweisen und keine Ausnahmen werfen. Die Konstruktion von d und des daraus kopierten gespeicherten Deleters darf keine Ausnahmen werfen.

Deleter muss CopyConstructible sein.

(bis C++17)

Diese Konstruktoren nehmen zusätzlich nicht an der Überladungsauflösung teil, wenn der Ausdruck d ( ptr ) nicht wohlgeformt ist oder wenn std:: is_move_constructible_v < D > false ist.

(seit C++17)
6,7) Gleich wie (4,5) , verwendet jedoch zusätzlich eine Kopie von alloc für die Allokation von Daten für interne Zwecke. Alloc muss ein Allocator sein.
8) Der Aliasing-Konstruktor : Erstellt einen shared_ptr , der Besitzinformationen mit dem Anfangswert von r teilt, aber einen unabhängigen und nicht verwalteten Zeiger ptr hält. Wenn dieser shared_ptr der letzte der Gruppe ist, der den Gültigkeitsbereich verlässt, wird er den gespeicherten Deleter für das ursprünglich von r verwaltete Objekt aufrufen. Allerdings gibt der Aufruf von get() auf diesem shared_ptr immer eine Kopie von ptr zurück. Es liegt in der Verantwortung des Programmierers, sicherzustellen, dass dieser ptr solange gültig bleibt, wie dieser shared_ptr existiert, wie in den typischen Anwendungsfällen, in denen ptr ein Mitglied des von r verwalteten Objekts ist oder ein Alias (z.B. Downcast) von r.get() ist. Für die zweite Überladung, die einen Rvalue nimmt, ist r leer und r. get ( ) == nullptr nach dem Aufruf. (seit C++20)
9) Konstruiert einen shared_ptr , der die Eigentümerschaft des durch r verwalteten Objekts teilt. Falls r kein Objekt verwaltet, verwaltet auch * this kein Objekt. Die Template-Überladung nimmt nicht an der Überladungsauflösung teil, falls Y* nicht implizit konvertierbar zu (bis C++17) kompatibel mit (seit C++17) T* ist.
10) Move-konstruiert einen shared_ptr aus r . Nach der Konstruktion enthält * this eine Kopie des vorherigen Zustands von r , r ist leer und sein gespeicherter Zeiger ist null. Die Template-Überladung nimmt nicht an der Überladungsauflösung teil, wenn Y* nicht implizit konvertierbar zu (bis C++17) kompatibel mit (seit C++17) T* ist.
11) Konstruiert einen shared_ptr , der die Besitzrechte des durch r verwalteten Objekts teilt. Y* muss implizit in T* konvertierbar sein. (bis C++17) Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn Y* kompatibel mit T* ist. (seit C++17) Beachten Sie, dass r. lock ( ) für denselben Zweck verwendet werden kann: Der Unterschied besteht darin, dass dieser Konstruktor eine Exception wirft, wenn das Argument leer ist, während std:: weak_ptr < T > :: lock ( ) in diesem Fall einen leeren std::shared_ptr konstruiert.
12) Konstruiert einen shared_ptr , der das zuvor von r besessene Objekt speichert und besitzt. Y* muss in T* konvertierbar sein. Nach der Konstruktion ist r leer.
13) Konstruiert einen shared_ptr , der das Objekt verwaltet, das aktuell von r verwaltet wird. Der mit r assoziierte Deleter wird für die zukünftige Löschung des verwalteten Objekts gespeichert. r verwaltet nach dem Aufruf kein Objekt mehr.
Diese Überladung nimmt nicht an der Überladungsauflösung teil, wenn std::unique_ptr<Y, Deleter>::pointer nicht kompatibel mit T* ist. Wenn r. get ( ) ein Nullzeiger ist, entspricht diese Überladung dem Standardkonstruktor (1) . (since C++17)
Wenn Deleter ein Referenztyp ist, entspricht dies shared_ptr ( r. release ( ) , std:: ref ( r. get_deleter ( ) ) . Andernfalls entspricht es shared_ptr ( r. release ( ) , std :: move ( r. get_deleter ( ) ) ) .

Wenn T kein Array-Typ ist, ermöglichen die Überladungen (3,4,6) shared_from_this mit ptr , und die Überladung (13) ermöglicht shared_from_this mit dem von r. release ( ) zurückgegebenen Zeiger.

Inhaltsverzeichnis

Parameter

ptr - ein Zeiger auf ein zu verwaltendes Objekt
d - ein Deleter zur Zerstörung des Objekts
alloc - ein Allokator für interne Allokationen
r - ein weiterer Smart Pointer zur gemeinsamen Nutzung oder Übernahme der Eigentümerschaft

Nachbedingungen

1,2) use_count() entspricht 0 und get() entspricht nullptr .
3-7) use_count() entspricht 1 und get() entspricht ptr .
8) get() entspricht ptr . Für die zweite Überladung ist r leer und r. get ( ) entspricht nullptr .
9) get() entspricht r. get ( ) und use_count() entspricht r. use_count ( ) .
10) r soll leer sein und r. get ( ) soll gleich nullptr sein, und * this soll der alte Wert von r sein.
11) use_count() entspricht r. use_count ( ) .
12) use_count() ist gleich 1 und r. get ( ) ist gleich nullptr .

Exceptions

3) std::bad_alloc falls der benötigte zusätzliche Speicher nicht beschafft werden konnte. Kann implementationsdefinierte Ausnahmen für andere Fehler werfen. Wenn eine Ausnahme auftritt, ruft dies delete ptr falls T kein Array-Typ ist, und ruft delete [ ] ptr andernfalls (seit C++17) auf.
4-7) std::bad_alloc falls die benötigte zusätzliche Speichermenge nicht beschafft werden konnte. Kann implementationsdefinierte Ausnahmen für andere Fehler werfen. d ( ptr ) wird aufgerufen, falls eine Ausnahme auftritt.
11) std::bad_weak_ptr wenn r. expired ( ) == true . Der Konstruktor hat in diesem Fall keine Auswirkung.
12) std::bad_alloc falls die benötigte zusätzliche Speichermenge nicht beschafft werden konnte. Kann implementationsdefinierte Ausnahmen für andere Fehler werfen. Dieser Konstruktor hat keine Wirkung, wenn eine Ausnahme auftritt.
13) Wenn eine Ausnahme ausgelöst wird, hat der Konstruktor keine Auswirkungen.

Hinweise

Ein Konstruktor aktiviert shared_from_this mit einem Zeiger ptr vom Typ U* bedeutet, dass er bestimmt, ob U eine eindeutige und zugängliche (seit C++17) Basisklasse besitzt, die eine Spezialisierung von std::enable_shared_from_this ist, und falls ja, wertet der Konstruktor if ( ptr ! = nullptr && ptr - > weak_this  . expired ( ) )
ptr - > weak_this = std:: shared_ptr < std:: remove_cv_t < U >>
( * this, const_cast < std:: remove_cv_t < U > * > ( ptr ) ) ;
aus.

Die Zuweisung an weak_this ist nicht atomar und steht in Konflikt mit jedem potenziell gleichzeitigen Zugriff auf dasselbe Objekt. Dies stellt sicher, dass zukünftige Aufrufe von shared_from_this() den Besitz mit dem std::shared_ptr teilen, der durch diesen Rohzeiger-Konstruktor erstellt wurde.

Der Test ptr - > weak_this  . expired ( ) im obigen Code stellt sicher, dass weak_this nicht neu zugewiesen wird, falls es bereits auf einen Besitzer verweist. Dieser Test ist ab C++17 erforderlich.

Die Überladungen für rohe Zeiger übernehmen die Eigentümerschaft des gezeigten Objekts. Daher führt die Konstruktion eines shared_ptr unter Verwendung der Überladung für rohe Zeiger für ein Objekt, das bereits von einem shared_ptr verwaltet wird, wie etwa durch shared_ptr ( ptr. get ( ) ) , wahrscheinlich zu undefiniertem Verhalten, selbst wenn das Objekt von einem von std::enable_shared_from_this abgeleiteten Typ ist.

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

In C++11 und C++14 ist es gültig, einen std:: shared_ptr < T > aus einem std:: unique_ptr < T [ ] > zu konstruieren:

std::unique_ptr<int[]> arr(new int[1]);
std::shared_ptr<int> ptr(std::move(arr));

Da der shared_ptr seinen Deleter (ein std:: default_delete < T [ ] > Objekt) vom std::unique_ptr übernimmt, wird das Array korrekt freigegeben.

Dies ist in C++17 nicht mehr erlaubt. Stattdessen sollte die Array-Form std:: shared_ptr < T [ ] > verwendet werden.

Beispiel

#include <iostream>
#include <memory>
struct Foo
{
    int id{0};
    Foo(int i = 0) : id{i} { std::cout << "Foo::Foo(" << i <<  ")\n"; }
    ~Foo() { std::cout << "Foo::~Foo(), id=" << id << '\n'; }
};
struct D
{
    void operator()(Foo* p) const
    {
        std::cout << "Call delete from function object. Foo::id=" << p->id << '\n';
        delete p;
    }
};
int main()
{
    {
        std::cout << "1) constructor with no managed object\n";
        std::shared_ptr<Foo> sh1;
    }
    {
        std::cout << "2) constructor with object\n";
        std::shared_ptr<Foo> sh2(new Foo{10});
        std::cout << "sh2.use_count(): " << sh2.use_count() << '\n';
        std::shared_ptr<Foo> sh3(sh2);
        std::cout << "sh2.use_count(): " << sh2.use_count() << '\n';
        std::cout << "sh3.use_count(): " << sh3.use_count() << '\n';
    }
    {
        std::cout << "3) constructor with object and deleter\n";
        std::shared_ptr<Foo> sh4(new Foo{11}, D());
        std::shared_ptr<Foo> sh5(new Foo{12}, [](auto p)
        {
            std::cout << "Call delete from lambda... p->id=" << p->id << '\n';
            delete p;
        });
    }
}

Ausgabe:

1) constructor with no managed object
2) constructor with object
Foo::Foo(10)
sh2.use_count(): 1
sh2.use_count(): 2
sh3.use_count(): 2
Foo::~Foo(), id=10
3) constructor with object and deleter
Foo::Foo(11)
Foo::Foo(12)
Call delete from lambda... p->id=12
Foo::~Foo(), id=12
Call delete from function object. Foo::id=11
Foo::~Foo(), id=11
**Übersetzungshinweise:** - "Run this code" wurde zu "Code ausführen" übersetzt - "Output" wurde zu "Ausgabe" übersetzt - Alle HTML-Tags, Attribute und Code-Bereiche wurden unverändert beibehalten - C++-spezifische Begriffe wie "constructor", "object", "deleter", "lambda", "function object" wurden nicht übersetzt - Die Formatierung und Struktur der HTML-Elemente wurde vollständig erhalten

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 3548 C++11 der Konstruktor von unique_ptr kopierte den Deleter bewegt stattdessen

Siehe auch

Erstellt einen Shared Pointer, der ein neues Objekt verwaltet
(Funktions-Template)
Erstellt einen Shared Pointer, der ein neues Objekt verwaltet, das mit einem Allokator alloziert wurde
(Funktions-Template)
Ermöglicht einem Objekt, einen shared_ptr zu erstellen, der auf sich selbst verweist
(Klassen-Template)