std::shared_ptr<T>:: shared_ptr
|
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
|
(since C++17) |
shared_ptr
ohne verwaltetes Objekt, d.h. einen leeren
shared_ptr
.
shared_ptr
mit
ptr
als Zeiger auf das verwaltete Objekt.
|
Für
(3,4,6)
muss
|
(bis C++17) |
|
Falls
|
(seit C++17) |
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)
|
|
(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) |
Alloc
muss ein
Allocator
sein.
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)
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.
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.
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.
shared_ptr
, der das zuvor von
r
besessene Objekt speichert und besitzt.
Y*
muss in
T*
konvertierbar sein. Nach der Konstruktion ist
r
leer.
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) |
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
Exceptions
T
kein Array-Typ ist, und ruft
delete
[
]
ptr
andernfalls
(seit C++17)
auf.
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
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) |
|
|
(C++11)
|
Ermöglicht einem Objekt, einen
shared_ptr
zu erstellen, der auf sich selbst verweist
(Klassen-Template) |